float - round decimals c++>
¿Por qué un molde de int flota alrededor del valor? (2)
Estoy leyendo CS: APP, y con respecto a los moldes, dice que cuando se lanza de int a float, el número no puede desbordarse, pero puede redondearse.
Me pareció extraño ya que no sabía lo que había para redondear, así que lo probé. Pensé que esto solo sería el caso para enteros muy grandes (cerca de INT_MAX
/ INT_MIN
), pero el redondeo también ocurre en valores de alrededor de cien millones. (No estoy seguro de dónde exactamente sucede esto primero).
¿Por qué pasó esto? El rango de float
supera con creces el de int
. Se podría decir que los números de coma flotante no se pueden representar exactamente, pero al convertir de int
a double
no hay cambio en el valor. La ventaja del double
sobre el float
es que tiene mayor alcance y precisión. Pero float
todavía tiene suficiente alcance para "encapsular" números enteros, y la precisión en realidad no debería importar ya que los enteros no tienen decimales (bueno, todos 0), ¿o estoy pensando mal?
Aquí hay algunos resultados que obtuve (aquí está el código: http://pastebin.com/K3E3A6Ni ):
FLT_MAX = 340282346638528859811704183484516925440.000000
INT_MAX = 2147483647
(float)INT_MAX = 2147483648.000000
(double)INT_MAX = 2147483647.000000
INT_MIN = -2147483648
(float)INT_MIN = -2147483648.000000
====other values close to INT_MIN INT_MAX====
INT_MAX-1 = 2147483646
(float)INT_MAX-1 = 2147483648.000000
INT_MIN+1 = -2147483647
(float)INT_MIN+1 = -2147483648.000000
INT_MAX-2 = 2147483645
(float)INT_MAX-2 = 2147483648.000000
INT_MAX-10 = 2147483637
(float)INT_MAX-10 = 2147483648.000000
INT_MAX-100 = 2147483547
(float)INT_MAX-100 = 2147483520.000000
INT_MAX-1000 = 2147482647
(float)INT_MAX-1000 = 2147482624.000000
(float)1.234.567.809 = 1234567808.000000
(float)1.234.567.800 = 1234567808.000000
(float)1.000.000.005 = 1000000000.000000
(float)800.000.003 = 800000000.000000
(float)500.000.007 = 500000000.000000
(float)100.000.009 = 100000008.000000
Supongo que por float
te refieres a un valor de punto flotante binario IEEE-754 de 32 bits, en el double
significas un valor de punto flotante binario IEEE-754 de 64 bits, y por int
te refieres a un entero de 32 bits.
¿Por qué pasó esto? El rango de flotación supera con creces el de int
Sí, pero la precisión del float
es solo 7-9 dígitos decimales. Para ser más específico, el significado es de solo 24 bits de ancho ... así que si estás tratando de almacenar 32 bits de información allí, vas a tener problemas.
pero al convertir de
int
adouble
no hay cambio en el valor
Claro, porque un double
tiene un significado de 53 bits, ¡hay mucho espacio para un entero de 32 bits!
Para pensarlo de otra manera, la brecha entre los valores int
consecutivos es siempre 1 ... mientras que la brecha entre los valores de float
consecutivos comienza muy, muy pequeño ... pero aumenta a medida que aumenta la magnitud del valor. Llega a "más de 2" mucho antes de llegar al límite de int
... por lo que llega al nivel donde no todas las int
pueden representarse exactamente.
Para pensarlo de otra manera, simplemente puede usar el principio del casillero ... incluso ignorando los valores NaN, puede haber como máximo 2 32 valores float
, y al menos uno de ellos no es el valor exacto de una toma int
. 0.5, por ejemplo. Hay 2 32 valores int
, por lo tanto, al menos un valor int
no tiene una representación float
exacta.
Un float
típico que se implementa con la representación IEEE-754 de 32 bits tiene solo 24 bits para el significado, lo que permite aproximadamente 7 dígitos decimales de precisión. Por lo tanto, verá el redondeo tan pronto como llegue a los millones (2 24 y aproximadamente; 16 millones).
(Para un double
, el significado tiene 53 bits, y 2 53 y aproximadamente; 9 × 10 15 ).