2011-10-15 18 views
13

Es sorprendente para mí ver que incluso cuando el valor se puede convertir, una conversión int a flotante siempre da una advertencia. ¿Por qué es esto?int para la conversión flotante produce una advertencia?

int i = 0; 
float f = 0; // warning here 

// I thought this was an implicit conversion, 
// meaning it is convertible with no warnings. 
f = i;  // another warning here 

La advertencia es:

warning C4244: '=' : conversion from 'int' to 'float', possible loss of data 
+1

Asigne el valor MAX INT al tipo de letra flotante y vea el resultado. –

+3

float f = 0.0f; // 0 es un número entero. –

+0

Da la misma advertencia con ambos 'f = MAXINT;' y 'f = INT_MAX;' – user103214

Respuesta

4

que respondió a una pregunta similar aquí:

Why does GCC warn against this implicit conversion?

La razón es que un int necesidades a ser redondeados cuando se cuela en una float porque float no puede contener toda la precisión de int en esta ca se.

En su caso, un float solo tiene unos 24 bits de precisión. Mientras que un int tiene 32 bits de precisión, por lo tanto, se pierde algo de precisión por este lanzamiento, de ahí la advertencia.

+0

Puede haber (y hay) implementaciones donde' float' puede contener todos los valores de tipo 'int' sin pérdida de información, por ejemplo si' int' y 'float' son 16 y 32 bits, respectivamente, o 32 y 64 bits. Pero los compiladores son libres de usar información sobre la implementación particular cuando deciden emitir una advertencia. –

+0

Me doy cuenta de que, por lo tanto, he insertado "en este caso" en mi respuesta, ya que no está definido como universalmente cierto. – Mysticial

10

Depende de la cantidad de bits que tenga en su tipo int. Un flotante con precisión simple IEEE754 es un valor de 32 bits, pero algunos de esos bits se asignan al exponente, lo que significa que no todos están disponibles para la precisión.

Si su tipo int tiene más precisión que su float, entonces puede sufrir pérdida de precisión en el extremo superior.

En otras palabras, es posible que no pueda distinguir entre INT_MAX y INT_MAX - 1.

La solución en ese caso es usar un tipo de punto flotante más ancho (double) aunque, técnicamente, puede encontrar una implementación que tenga un tipo int de 256 bits, en cuyo caso deberá encontrar otra forma :-)

This answer tiene una breve descripción de cómo funcionan los formatos de coma flotante, incluido el hecho de que solo 23 de los 32 bits están disponibles para la precisión de la mantisa.

3

Sólo por diversión, probar esto y ver lo que la salida es (pista, que se puede esperar de los números a ser todos iguales, ¿verdad?):

int i1(INT_MAX), i2; 

float f(i1); 

i2 = f; 

std::cout << i1 << ' ' << f << ' ' << i2 << '\n'; 

Bueno, las respuestas que recibo son:

2147483647 2.14748e+009 -2147483648 

lo que el compilador tiene toda la razón en señalar que algo puede ir mal con el elenco, pero no es lo suficientemente inteligente para saber con seguridad, ya que sólo tienden a ocurrir en las extremidades de el rango numérico. Siempre es mejor para static_cast <> en mi opinión, para mayor claridad al menos, y para mostrar al compilador que era lo que pretendía.

Por cierto, no estoy del todo seguro de por qué ocurre el resultado anterior. ¡Quizás alguien más pueda explicar!

+0

Me da dos advertencias, una sobre la inicialización del flotador y otra sobre la conversión a flotación. – user103214

+0

@ user974191: Eso no quedó claro a partir de su pregunta original. Lo he actualizado para reflejar esa información (aunque estoy un poco sorprendido de que haya advertido sobre 'float f = 0;'). Por favor revisa mis ediciones. –

1

// pensé que esto era implícita conversión significa que es covertible con ninguna advertencia?

No, eso no es lo que significa. Simplemente significa que puede asignar un valor de un tipo a un objeto de otro tipo sin una conversión explícita (es decir, un molde), y el valor se convertirá implícitamente.

Y en este caso, una advertencia podría ser apropiada. Si int y float son ambos de 32 bits (que es típico pero no universal), entonces todos los valores de tipo int están dentro del rango de float, pero hay muchos valores de tipo int que no se pueden representar exactamente en tipo float.

El estándar de idioma requiere al menos un mensaje de diagnóstico para cualquier unidad de traducción (archivo fuente) que viole una regla o restricción de sintaxis. Pero los compiladores pueden emitir cualquier diagnóstico adicional que les guste.

+0

Hay una restricción importante en el diagnóstico de compilador adicional: el compilador no puede emitir tantos diagnósticos que imposibilite la compilación de un programa que cumpla con los estándares. Ha habido algunos compiladores (no sé si todavía existen) que podrían morir si una línea produce demasiadas advertencias. Si bien sería inusual que una línea generara miles de advertencias, sería posible que un programa compilador de estándares lo hiciera con macroexpansiones. – supercat

+0

@supercat: Esto se aplica igualmente a cualquier cosa que haga el compilador, no solo a los diagnósticos. Lo que estás describiendo es solo un error del compilador; Normalmente, la emisión de innumerables advertencias no causaría la falla de un compilador. Y el estándar permite que los compiladores fallen debido a los límites de capacidad; solo requiere traducir y ejecutar un programa * single * que alcance todos los límites especificados (C99 5.2.4.1). –

Cuestiones relacionadas