2010-10-29 14 views
9

¿Alguien puede explicar por qué multiplicar por 100 aquí da un resultado menos preciso pero al multiplicar por 10 dos veces se obtiene un resultado más preciso?ruby ​​floating point errors

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

Lo más probable debido a la representación binaria de los números de punto flotante. No se puede escribir exctamente 129.95 en la base 2, supongo. –

+10

Enlace obligatorio: [Lo que todo científico informático debe saber sobre la aritmética de coma flotante] (http://docs.sun.com/source/806-3568/ncg_goldberg.html) –

+0

Cualquier pista sobre por qué esto NO estaría sucediendo para ¿yo? Intento demostrar esto, y entro en 129.95 * 100 como arriba en IRB e inesperadamente recibo la respuesta correcta. – Joel

Respuesta

22

Si lo hace los cálculos a mano en binario de doble precisión, que se limita a 53 bits significativos, verá lo que está pasando:

129,95 = 1,0000001111100110011001100110011001100110011001100110 x 2^7

129,95 * 100 = 1.1001011000010111111111111111111111111111111111111111011 x 2^13

Esto es 56 bits significativos de largo, de modo redondeado a 53 bits que es

1,10010110000101111111111111111111111111111111111111 11 x 2^13, que es igual

12994,999999999998181010596454143524169921875

Ahora 129,95 * 10 = 1.01000100110111111111111111111111111111111111111111111 x 2^10

Este es de 54 bits significativos de largo, de modo redondeado a 53 bits Es 1,01000100111 x 2^10 = 1299,5

Ahora 1.299,5 * 10 = 1.1001011000011 x 2^13 = 12995.

3

En primer lugar: está viendo la representación de la cadena del resultado, no el resultado real en sí. 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 de coma flotante binarios. 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.

2

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".