2010-01-04 26 views
7

Me encontré con estos valores en mi código de ColdFusion, pero la calculadora de Google parece tener el mismo "error" cuando la diferencia es distinta de cero.¿Por qué esta resta no es igual a cero?

416.582,2850-411.476,8100 - 5.105,475 = -2.36468622461E-011

http://www.google.com/search?hl=en&rlz=1C1GGLS_enUS340US340&q=416582.2850+-+411476.8100+-+5105.475&aq=f&oq=&aqi=

JavaCast'ing estos a largo/float/double no Ayuda- que se traduce en otras diferencias que no son cero.

+16

Debe haber una prueba de coma flotante al crear una cuenta en SO. Creo que esta es la pregunta más frecuente en el sitio. – recursive

+3

@recursive: http://meta.stackexchange.com/questions/26621/whats-the-most-repeated-question-on-stackoverflow/26633#26633 –

+1

Cuando aprendí a programar, la falta de precisión en los números de coma flotante se mencionó la primera vez que se discutió el punto flotante, y varias veces después de eso. ¿No lo hacen más? –

Respuesta

16

Esto se debe a que los números decimales que "se ven" en la base 10, no son exactamente representables en la base 2 (que es lo que las computadoras usan para representar números en coma flotante). Consulte el artículo What Every Computer Scientist Should Know About Floating-Point Arithmetic para obtener una explicación detallada de este problema y las soluciones alternativas.

+1

5105.475 era el número que no era representable exactamente en un doble. PrecisionEvaluate es la función ColdFusion que necesitaba. –

+0

En realidad, ninguno de esos números es exactamente representable como valores de doble precisión. –

+0

+1 referencia excelente, también consulte "Cómo imprimir números de punto flotante con precisión" por GL Steele –

7

imprecisiones de punto flotante (hay un número infinito de números reales y solo un número finito de números de 32 o 64 bits para representarlos).

Si no puede manejar pequeños errores, debe usar BigDecimal en su lugar.

+1

Referencia: http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems –

+0

Pero 416582.2850 - 411476.8100 se pueden representar * exactamente * como 5105.475. Estos son números con solo 4 decimales, no se repiten. ¿Son 4 decimales demasiado precisos? –

+2

No es la representación de base 10 la que tiene que ser finita, es la representación de base 2. Consulte http://en.wikipedia.org/wiki/Binary_numeral_system#Fractions_in_binary para obtener una explicación de qué fracciones se pueden representar exactamente en binario (son solo aquellas que tienen 2 como factor principal del denominador). –

1

El problema es la representación inexacta de los tipos de coma flotante. Debido a que estos no se pueden representar exactamente como flotantes, se obtiene una pérdida de precisión que hace que las operaciones tengan pequeños errores. Por lo general, con los flotantes que desea comparar si el resultado es igual a otro valor dentro de una pequeña epislon (factor de error).

2

Como la computadora almacena números en binario, los números de flotación son imprecisos. 1E-11 es una pequeña diferencia debido al redondeo de estos números decimales al número binario representable más cercano.

2

Este "error" no es un error. Así es como funciona la aritmética de coma flotante. Ver: http://docs.sun.com/source/806-3568/ncg_goldberg.html

Si desea precisión arbitraria en Java, utilice BigDecimal:

BigDecimal a = new BigDecimal("416582.2850"); 
    BigDecimal b = new BigDecimal("411476.8100"); 
    BigDecimal c = new BigDecimal("5105.475"); 
    System.out.println(a.subtract(b).subtract(c)); // 0.0 
1

Estos son problemas de punto flotante y el uso de BigDecimal lo arreglará.

Cambiar el orden de resta también arroja cero en Google.

416582.2850 - 5105.475 - 411476.8100 = 0 
5

Uso PrecisionEvaluate() en ColdFusion (que va a utilizar BigDecimal en Java)

zero = PrecisionEvaluate(416582.2850 - 411476.8100 - 5105.475); 

a diferencia Evaulate(), no "" se necesita.

+1

+1 para la solución de fusión en frío real – Kip

Cuestiones relacionadas