Problema
El punto flotante no puede almacenar todos los valores decimales exactamente. Por lo tanto, cuando se utilizan formatos de punto flotante, siempre habrá errores de redondeo en los valores de entrada. Los errores en las entradas, por supuesto, resultan en errores en la salida. En el caso de una función u operador discreto, puede haber grandes diferencias en la salida alrededor del punto donde la función u operador es discreto.
Entrada y salida para valores de coma flotante
Por lo tanto, cuando use variables de punto flotante, siempre debe ser consciente de esto. Y cualquier salida que desee de un cálculo con puntos flotantes siempre debe formatearse / condicionarse antes de mostrarse con esto en mente.
Cuando solo se utilizan operadores y funciones continuas, a menudo se redondea a la precisión deseada (no se trunca). Las características de formato estándar que se utilizan para convertir flotantes en cadenas generalmente lo harán por usted.
Debido a que el redondeo agrega un error que puede causar que el error total sea más de la mitad de la precisión deseada, la salida debe corregirse según la precisión esperada de las entradas y la precisión deseada de la salida. Debieras
- Redondee las entradas a la precisión esperada o asegúrese de que no se puedan ingresar valores con mayor precisión.
- Agregue un valor pequeño a las salidas antes de redondearlas / formatearlas, que sea menor o igual a 1/4 de la precisión deseada y mayor que el error máximo esperado causado por los errores de redondeo en la entrada y durante el cálculo. Si eso no es posible, la combinación de la precisión del tipo de datos utilizado no es suficiente para proporcionar la precisión de salida deseada para su cálculo.
Estas 2 cosas generalmente no se hacen y, en la mayoría de los casos, las diferencias causadas por no hacerlo son demasiado pequeñas para ser importantes para la mayoría de los usuarios, pero ya tenía un proyecto en el que los usuarios no aceptaban los resultados sin esas correcciones.
Funciones u operadores discretos (como módulo)
Cuando intervienen operadores o funciones discretas, es posible que se requieran correcciones adicionales para asegurarse de que el resultado sea el esperado. Redondear y agregar pequeñas correcciones antes de redondear no puede resolver el problema.
Es posible que se requiera una verificación / corrección especial en los resultados de cálculo intermedios, inmediatamente después de aplicar la función u operador discreto. Para un caso específico (operador de módulo), vea mi respuesta a la pregunta: ¿Por qué el operador de módulo devuelve un número fraccionario en javascript?
Mejor evitar tener el problema
A menudo es más eficiente evitar estos problemas mediante el uso de tipos de datos (formatos enteros o de punto fijo) para cálculos como este, que pueden almacenar la entrada esperada sin errores de redondeo. Un ejemplo de esto es que nunca debe usar valores de punto flotante para cálculos financieros.
0.1
a un número finito de punto flotante binario.