2008-11-29 41 views
9

En mi programa que tiene una matriz con 25 valores dobles 0,04 Cuando trato de resumir estos valores en un bucle consigo siguientes resultados:comportamiento de punto flotante extraño en un programa Java

0.0 + 0.04 = 0.04 
0.04 + 0.04 = 0.08 
0.08 + 0.04 = 0.12 
0.12 + 0.04 = 0.16 
0.16 + 0.04 = 0.2 
0.2 + 0.04 = 0.24000000000000002 
0.24000000000000002 + 0.04 = 0.28 
0.28 + 0.04 = 0.32 
0.32 + 0.04 = 0.36 
0.36 + 0.04 = 0.39999999999999997 
0.39999999999999997 + 0.04 = 0.43999999999999995 
0.43999999999999995 + 0.04 = 0.4799999999999999 
0.4799999999999999 + 0.04 = 0.5199999999999999 
0.5199999999999999 + 0.04 = 0.5599999999999999 
0.5599999999999999 + 0.04 = 0.6 
0.6 + 0.04 = 0.64 
0.64 + 0.04 = 0.68 
0.68 + 0.04 = 0.7200000000000001 
0.7200000000000001 + 0.04 = 0.7600000000000001 
0.7600000000000001 + 0.04 = 0.8000000000000002 
0.8000000000000002 + 0.04 = 0.8400000000000002 
0.8400000000000002 + 0.04 = 0.8800000000000002 
0.8800000000000002 + 0.04 = 0.9200000000000003 
0.9200000000000003 + 0.04 = 0.9600000000000003 

¿Por qué en la tierra ¿podría pasar eso?

+0

pregunta Poco relacionado: http://stackoverflow.com/questions/327020/why-are-floating-point-values-so-prolific – CesarB

Respuesta

23

El almacenamiento más común para los valores de punto flotante en lenguajes de programación - IEEE singles and doubles - no tiene representaciones exactas para la mayoría de las fracciones decimales.

La razón es que se almacenan los valores en formato de punto flotante binario, en lugar del formato de coma flotante decimal. Los únicos valores fraccionarios que pueden representarse exactamente son aquellos que son sumas de potencias negativas de dos. Números como:

  • 0,5 (2^-1)
  • 0,125 (2^-3)
  • 0,625 (2^-1 + 2^-3)

Etc.

lo que está viendo es el hecho de que las representaciones de números como 0,96 no son exactamente representable, porque no se pueden expresar como una suma de potencias negativas de dos. Por lo tanto, cuando se imprimen con total precisión como una fracción decimal, no coincidirán con el valor original.

+0

"En lugar de decimales" un poco da una idea equivocada. Si utilizara decimal, estaría limitado a valores fraccionarios que son sumas de potencias negativas de diez, por lo que no resolvería mucho. Alguien que lea su respuesta puede tener la idea de que "el problema desaparecería si solo usaran base10" – jalf

+0

@jalf, cierto, pero al menos una representación de coma flotante decimal sorprendería a menos personas acostumbradas a la contabilidad simple de bolsillo. Sumar una pila de 20 monedas de 5 centavos y no obtener exactamente una pelota es sorprendente para mucha gente. Una notación decimal acertaría en ese caso, y cambiaría eso por problemas graciosos con números que deberían estar familiarizados con las lecciones de aritmética de la escuela primaria. – RBerteig

14
+0

Ese documento es muy denso para alguien nuevo en la representación de coma flotante en la mayoría de los lenguajes de programación.No lo recomendaría fuera de las personas con al menos un año, sino tres, en educación CS. –

+0

Estoy de acuerdo. Por otro lado, es bueno para los practicantes autodidactas y para los esforzados en saber dónde están, en caso de que estén enfrentando problemas numéricos. –

+3

Todavía es algo que las personas deberían saber, aunque sea demasiado denso para que lo lean. ;) – jalf

5

Otras respuestas mencionan por qué, pero no la forma de evitarlo.

hay varias soluciones:

  • Escala: si todos los números son múltiplos de 0,01 (por ejemplo), se multiplica todo por 100 y el uso de aritmética de enteros (que es exacta).
  • tipo numérico: si su lenguaje tiene un tipo numérico (como un tipo numeric en SQL), que se puede utilizar.
  • racionales de precisión arbitraria: use una biblioteca bignum como GMP, que permite representar estos números como el cociente de dos números enteros.
  • decimal de coma flotante: si tiene un punto decimal como el que flota en IEEE-754r, que se puede utilizar.
+0

+1 para racionales – finnw

1

Es posible que desee comprobar la clase java BigDecimal como una alternativa a los flotadores y los dobles.

Cuestiones relacionadas