c++ c floating-point type-conversion precision

c++ - Precisión de la multiplicación por 1.0 e int a la conversión de flotación



floating-point type-conversion (4)

¿Es seguro asumir que la condición (int)(i * 1.0f) == i es verdadera para cualquier número entero i ?


No, los números de coma flotante IEEE-754 tienen un rango dinámico mayor que los enteros a costa de una precisión entera para el mismo ancho de bit.

Ver por ejemplo el resultado de este pequeño fragmento:

int main() { int x = 43046721; float y = x; printf("%d/n", x); printf("%f/n", y); }

43046721 no se puede representar correctamente en los 24 bits de precisión disponibles en un número float 32 bits, por lo que el resultado es algo 43046721 lo siguiente:

43046721 43046720.000000

De hecho, esperaría que cualquier número impar por encima de 16.777.216 tenga el mismo problema al convertir a un número float 32 bits.

Algunos puntos de interés:

  • Esto tiene más que ver con la conversión implícita de flotación que con la multiplicación misma.

  • Esto no es de ninguna manera exclusivo de C, por ejemplo, Java también está sujeto al mismo problema.

  • La mayoría de los compiladores tienen opciones de optimización que pueden afectar la forma en que se manejan dichas conversiones, ignorando ciertas restricciones del estándar. En tal caso, (int)((float)x * 1.0f) == x siempre podría ser true si el compilador optimiza la conversión a float y viceversa.


No.

Si i es suficientemente grande que int(float(i)) != i (suponiendo que float es IEEE-754 de precisión simple, i = 0x1000001 suficiente para exhibir esto) entonces esto es falso, porque la multiplicación por 1.0f fuerza a una conversión a float , que cambia el valor aunque la multiplicación posterior no lo haga.

Sin embargo, si i soy un entero de 32 bits y el double es double IEEE-754, entonces es cierto que int(i*1.0) == i .

Para ser totalmente claro, la multiplicación por 1.0f es exacta. Es la conversión de int a float que puede no ser.


No, es absolutamente incorrecto para todos los enteros debido al tipo de molde. Código de verificación.

#include <stdio.h> int main() { int i = 0; for (; i < 2147483647; ++i) { if ((int)(i * 1.0f) != i) { printf("not equal/n"); break; } } printf("out of the loop/n"); getchar(); return 0; }

Este código supone que toma un entero de 32 bits


No, el comportamiento es implementación definida porque C y C ++ no requieren IEEE-754, aunque esa es la representación más común de lejos.

Para estar seguro de que se usa IEEE-754:

  • en C, use #ifdef __STDC_IEC_559__
  • en C ++, use las std::numeric_limits<float>::is_iec559