¿Qué sucede en C ++ cuando un tipo entero se convierte en un tipo de punto flotante o viceversa?

¿Los bits subyacentes simplemente se “reinterpretan” como un valor de punto flotante? ¿O hay una conversión en tiempo de ejecución para producir el valor de punto flotante más cercano?

¿El endianismo es un factor en alguna plataforma (es decir, el endianness de los flotadores difiere de los ints)?

¿Cómo se comportan los diferentes tipos de ancho (por ejemplo, int para flotar vs. int para duplicar)?

¿Qué garantiza el estándar de idioma sobre la seguridad de tales conversiones / conversiones? Por reparto, me refiero a un static_cast o un reparto de estilo C.

¿Qué pasa con la conversión inversa de float a int (o doble a int)? Si un flotador tiene un valor de magnitud pequeño (por ejemplo, 2), ¿el patrón de bits tiene el mismo significado cuando se interpreta como un int?

¿Los bits subyacentes simplemente se “reinterpretan” como un valor de punto flotante?

No, el valor se convierte de acuerdo con las reglas del estándar.

¿hay una conversión en tiempo de ejecución para producir el valor de punto flotante más cercano?

Sí, hay una conversión en tiempo de ejecución.

Para coma flotante -> entero, el valor se trunca, siempre que el valor de origen esté en el rango del tipo entero. Si no lo es, el comportamiento es indefinido. Al menos creo que lo que importa es el valor de origen, no el resultado. Tendría que buscarlo para estar seguro. El caso límite si el tipo de destino es char, por ejemplo, sería CHAR_MAX + 0.5 . Creo que está indefinido lanzar eso a char, pero como digo no estoy seguro.

Para entero -> punto flotante, el resultado es el mismo valor exacto si es posible, o bien es uno de los dos valores de punto flotante a cada lado del valor entero. No necesariamente el más cercano de los dos.

¿El endianismo es un factor en alguna plataforma (es decir, el endianness de los flotadores difiere de los ints)?

No nunca. Las conversiones se definen en términos de valores, no de representaciones de almacenamiento.

¿Cómo se comportan los diferentes tipos de ancho (por ejemplo, int para flotar vs. int para duplicar)?

Todo lo que importa son los rangos y precisiones de los tipos. Suponiendo que los ints de 32 bits y los flotadores IEEE de 32 bits, es posible que una conversión int-> float sea imprecisa. Suponiendo que también se duplica el IEEE de 64 bits, no es posible que una conversión int-> double sea imprecisa, porque todos los valores int pueden representarse exactamente como un doble.

¿Qué garantiza el estándar de idioma sobre la seguridad de tales conversiones / conversiones? Por reparto, me refiero a un static_cast o un reparto de estilo C.

Como se indicó anteriormente, es seguro, excepto en el caso de que un valor de punto flotante se convierta en un tipo entero y el valor esté fuera del rango del tipo de destino.

Si un flotador tiene un valor de magnitud pequeño (por ejemplo, 2), ¿el patrón de bits tiene el mismo significado cuando se interpreta como un int?

No, no lo hace. La representación IEEE de 32 bits de 2 es 0x40000000 .

Como referencia, esto es lo que dice ISO-IEC 14882-2003

4.9 Conversiones flotantes-integrales

Un rvalor de un tipo de punto flotante se puede convertir en un rvalor de un tipo entero. La conversión trunca; es decir, se desecha la parte fraccionaria. El comportamiento no está definido si el valor truncado no se puede representar en el tipo de destino. [Nota: Si el tipo de destino es `bool, vea 4.12. ]

Un rvalue de un tipo entero o de un tipo de enumeración se puede convertir en un rvalue de un tipo de punto flotante. El resultado es exacto si es posible. De lo contrario, es una opción definida por la implementación del siguiente valor representable más bajo o más alto. [Nota: la pérdida de precisión ocurre si el valor integral no se puede representar exactamente como un valor del tipo flotante. ] Si el tipo de fuente es bool , el valor false se convierte en cero y el valor true se convierte en uno.

Referencia: lo que todo científico informático debe saber sobre la aritmética de punto flotante

Otras referencias de gran valor sobre el tema de las conversiones de float rápida a int :

  • Conoce tu FPU
  • Vayamos al punto (flotante)
  • Conoce tu FPU: Arreglando Flotante Rápido

¡Tenga una buena lectura!

Normalmente hay conversiones en tiempo de ejecución, ya que las representaciones de bits generalmente no son compatibles (con la excepción de que el 0 binario es normalmente 0 y 0.0). Los estándares C y C ++ tratan solo con el valor, no la representación, y especifican un comportamiento generalmente razonable. Recuerde que un valor int grande no será normalmente representable exactamente en un float , y un valor float grande no puede representarse mediante un int .

Por lo tanto:

Todas las conversiones son por valor, no por patrones de bits. No te preocupes por los patrones de bits.

Tampoco te preocupes por el endianismo, ya que es una cuestión de representación a nivel de bits.

Convertir int a float puede perder precisión si el valor entero es grande en valor absoluto; es menos probable que lo haga con el double , ya que el double es más preciso y puede representar muchos más números exactos. (Los detalles dependen de qué representaciones está usando realmente el sistema).

Las definiciones de lenguaje no dicen nada acerca de los patrones de bits.

La conversión de float a int también es una cuestión de valores, no de patrones de bits. Un punto flotante exacto 2.0 se convertirá en una integral 2 porque así es como se configura la implementación, no debido a los patrones de bits.

Cuando convierte un entero en un flotador, no es probable que pierda ninguna precisión a menos que se trate de enteros extremadamente grandes.

Cuando convierte un flotador a un int, básicamente está realizando la operación floor (). por lo que simplemente deja caer los bits después del decimal

Para obtener más información sobre el punto flotante, lea: http://www.lahey.com/float.htm

El formato de precisión simple IEEE tiene 24 bits de mantisa, 8 bits de exponente y un bit de signo. Los registros internos de punto flotante en microprocesadores Intel, como el Pentium, tienen 64 bits de mantisa, 15 bits de exponente y un bit de signo. Esto permite que los cálculos intermedios se realicen con mucha menos pérdida de precisión que muchas otras implementaciones. El aspecto negativo de esto es que, dependiendo de cómo se mantengan los valores intermedios en los registros, los cálculos que se ven iguales pueden dar resultados diferentes.

Entonces, si su entero usa más de 24 bits (excluyendo el bit inicial oculto), es probable que pierda algo de precisión en la conversión.

Reinterpretado? El término “reinterpretación” generalmente se refiere a la reinterpretación de la memoria sin procesar. Por supuesto, es imposible reinterpretar de manera significativa un valor entero como un valor de punto flotante (y viceversa), ya que sus representaciones físicas generalmente son completamente diferentes.

Cuando emite los tipos, se realiza una conversión en tiempo de ejecución (a diferencia de la reinterpretación ). La conversión normalmente no es solo conceptual, requiere un esfuerzo de tiempo de ejecución real, debido a la diferencia en la representación física. No hay relaciones definidas por idioma entre los patrones de bits de los valores de origen y destino. La endianidad tampoco desempeña ningún papel en ella.

Cuando convierte un valor entero a un tipo de punto flotante, el valor original se convierte exactamente si puede representarse exactamente por el tipo de destino. De lo contrario, el valor será cambiado por el proceso de conversión.

Cuando convierte un valor de punto flotante a un tipo entero, la parte fraccionaria simplemente se descarta (es decir, no se toma el valor más cercano, pero el número se redondea hacia cero). Si el resultado no se ajusta al tipo de entero objective, el comportamiento no está definido.

También tenga en cuenta que las conversiones de punto flotante a entero (y lo contrario) son conversiones estándar y formalmente no requieren conversión explícita de ningún tipo. Las personas a veces pueden usar una conversión explícita para suprimir las advertencias del comstackdor.

Si emite el valor en sí, se convertirá (por lo tanto, en una flotación -> la conversión int 3.14 se convierte en 3).

Pero si lanza el puntero, en realidad “reinterpretará” los bits subyacentes. Así que si haces algo como esto:

 double d = 3.14; int x = *reinterpret_cast(&d); 

x tendrá un valor ‘aleatorio’ que se basa en la representación del punto flotante.

La conversión de FP a tipo integral no es trivial y ni siquiera está completamente definida.

Normalmente, su FPU implementa una instrucción de hardware para convertir de formato IEEE a int . Esa instrucción podría tomar parámetros (implementados en hardware) que controlan el redondeo. Su ABI probablemente especifica redondeo al más cercano. Si está usando X86 + SSE, “probablemente no sea demasiado lento”, pero no puedo encontrar una referencia con una búsqueda de Google.

Como con cualquier cosa FP, hay casos de esquina. Sería bueno si el infinito se (TYPE)_MAX a (TYPE)_MAX pero, por desgracia, no es el caso, el resultado de int x = INFINITY; es indefinido.