ruby floating floating errors

¿Puede alguien explicar por qué multiplicar por 100 aquí da un resultado menos preciso pero multiplicar por 10 dos veces da un resultado más preciso?

± % sc Loading development environment (Rails 3.0.1) >> 129.95 * 100 12994.999999999998 >> 129.95*10 1299.5 >> 129.95*10*10 12995.0 

Si realiza los cálculos a mano en binario de precisión doble, que está limitado a 53 bits significativos, verá lo que está sucediendo:

129.95 = 1.0000001111100110011001100110011001100110011001100110 x 2 ^ 7

129.95 * 100 = 1.1001011000010111111111111111111111111111111111111111011 x 2 ^ 13

Esto es 56 bits significativos de largo, tan redondeado a 53 bits es

1.1001011000010111111111111111111111111111111111111111 x 2 ^ 13, lo que equivale

12994.999999999998181010596454143524169921875

Ahora 129.95 * 10 = 1.01000100110111111111111111111111111111111111111111111 x 2 ^ 10

Esto es 54 bits significativos de largo, tan redondeado a 53 bits es 1.01000100111 x 2 ^ 10 = 1299.5

Ahora 1299.5 * 10 = 1.1001011000011 x 2 ^ 13 = 12995.

En primer lugar, está viendo la representación de cadena del resultado, no el resultado real en sí mismo. Si realmente desea comparar los dos resultados, debe formatear ambos resultados explícitamente, usando String#% y debe formatear ambos resultados de la misma manera.

En segundo lugar, así es como funcionan los números binarios de coma flotante. Son inexactos, son finitos y binarios. Los tres significan que tienes errores de redondeo, que generalmente se ven totalmente al azar, a menos que hayas memorizado la totalidad de IEEE754 y puedas recitarla al revés mientras duermes.

No hay un número de coma flotante exactamente igual a 129.95 . Entonces, su lenguaje usa un valor que está cerca de él. Cuando ese valor se multiplica por 100, el resultado es cercano a 12995, pero sucede que no es igual a 12995. (Tampoco es exactamente igual a 100 veces el valor original que usó en lugar de 129.95 ). Así que su intérprete imprime un número decimal que es cercano (pero no igual) al valor de 129.95 * 100 y que muestra que no es exactamente 12995. También sucede que el resultado 129.95 * 10 es exactamente igual a 1299.5. Esto es mayormente suerte.

En pocas palabras, nunca espere igualdad de cualquier aritmética de coma flotante, solo “cercanía”.