Precisión de punto flotante de C ++

Posible duplicado:
Ejemplos de inexactitud de punto flotante

double a = 0.3; std::cout.precision(20); std::cout << a << std::endl; 

resultado: 0.2999999999999999889

 double a, b; a = 0.3; b = 0; for (char i = 1; i <= 50; i++) { b = b + a; }; std::cout.precision(20); std::cout << b << std::endl; 

resultado: 15.000000000000014211

Entonces … ‘a’ es más pequeño de lo que debería ser. Pero si tomamos ‘a’ 50 veces, el resultado será más grande de lo que debería ser.

¿Por qué es esto? ¿Y cómo obtener el resultado correcto en este caso?

Para obtener los resultados correctos, no establezca una precisión mayor que la disponible para este tipo numérico:

 #include  #include  int main() { double a = 0.3; std::cout.precision(std::numeric_limits::digits10); std::cout << a << std::endl; double b = 0; for (char i = 1; i <= 50; i++) { b = b + a; }; std::cout.precision(std::numeric_limits::digits10); std::cout << b << std::endl; } 

Aunque si ese bucle se ejecuta en 5.000 iteraciones en lugar de 50, el error acumulado aparecerá incluso con este enfoque: así es como funcionan los números de coma flotante.

¿Por qué es esto?

Debido a que los números de punto flotante se almacenan en binario, en el que 0.3 es 0.01001100110011001 … repetir al igual que 1/3 es 0.333333 … se repite en decimal. Cuando escribe 0.3 , en realidad obtiene 0.299999999999999988897769753748434595763683319091796875 (la representación binaria infinita redondeada a 53 dígitos significativos).

Tenga en cuenta que para las aplicaciones para las que está diseñado el punto flotante, no es un problema que no pueda representar exactamente 0.3. El punto flotante fue diseñado para ser utilizado con:

  • Las mediciones físicas, que a menudo se miden solo a 4 sig higos y nunca a más de 15.
  • Las funciones trascendentales, como los logaritmos y las funciones trigonométricas, que solo se aproximan de todos modos.

Para las cuales las conversiones decimales binarias son bastante irrelevantes en comparación con otras fonts de error.

Ahora, si está escribiendo software financiero, para el cual $ 0,30 significa exactamente $ 0,30, es diferente. Hay clases de aritmética decimal diseñadas para esta situación.

¿Y cómo obtener el resultado correcto en este caso?

Limitar la precisión a 15 dígitos significativos suele ser suficiente para ocultar los dígitos de “ruido”. A menos que realmente necesite una respuesta exacta, este es generalmente el mejor enfoque.

Las computadoras almacenan números en coma flotante en binario, no en decimal.

Muchos números que parecen normales en decimales, como 0.3, no tienen una representación exacta de la longitud finita en binario.
Por lo tanto, el comstackdor elige el número más cercano que tiene una representación binaria exacta, al igual que escribe 0.33333 para 1⁄3 .

Si agrega muchos números de coma flotante, estas pequeñas diferencias se acumulan y obtiene resultados inesperados.

No es que sea más grande o más pequeño, es solo que es físicamente imposible almacenar “0.3” como un valor exacto dentro de un número de punto flotante binario.

La forma de obtener el resultado “correcto” es no mostrar 20 decimales.

Para obtener el resultado “correcto”, intente

Lista de bibliotecas aritméticas de precisión arbitraria de Wikipedia: http://en.wikipedia.org/wiki/Arbitrary-precision

o

http://speleotrove.com/decimal