Si te pregunto ¿cuanto es 0,1 + 0,2? Puede que me mires en blanco, 0,1 + 0,2 = 0,3 Ah, ¿todavía necesitas preguntar? Incluso los niños del jardín de infancia pueden responder a una pregunta tan pediátrica. Pero ya sabes, el mismo problema en un lenguaje de programación puede no ser tan simple como se imagina.
¿No lo crees? Primero veamos una parte de JS.
var númA = 0,1;
var número B = 0,2;
alerta ((númA + númB) === 0,3);
El resultado de la ejecución es falso. Sí, cuando vi este código por primera vez, di por sentado que era cierto, pero los resultados de la ejecución me sorprendieron. ¿Mi método de apertura es incorrecto? No, no. Intentemos ejecutar el siguiente código nuevamente y sabremos por qué el resultado es falso.
var númA = 0,1;
var número B = 0,2;
alerta(númA + númB);
Resulta que 0,1 + 0,2 = 0,30000000000000004. ¿No es raro? De hecho, para las cuatro operaciones aritméticas de números de punto flotante, casi todos los lenguajes de programación tendrán problemas similares a los errores de precisión. Sin embargo, en lenguajes como C++/C#/Java, los métodos se han encapsulado para evitar problemas de precisión. Y JavaScript es un tipo débil. El lenguaje no tiene un tipo de datos estricto para números de punto flotante desde el concepto de diseño, por lo que el problema del error de precisión es particularmente prominente. Analicemos por qué existe este error de precisión y cómo solucionarlo.
En primer lugar, tenemos que pensar en el problema aparentemente pediátrico de 0,1 + 0,2 desde una perspectiva informática. Sabemos que lo que las computadoras pueden leer es binario, no decimal, así que primero conviertamos 0.1 y 0.2 a binario y echemos un vistazo:
0,1 => 0,0001 1001 1001 1001… (bucle infinito)
0,2 => 0,0011 0011 0011 0011… (bucle infinito)
La parte decimal de un número de coma flotante de doble precisión admite hasta 52 bits, por lo que después de sumar los dos, obtenemos una cadena de 0,0100110011001100110011001100110011001100110011001100. El número binario se trunca debido a la limitación de lugares decimales de los números de punto flotante. En este momento, lo convertimos a decimal y se convierte en 0,30000000000000004.
Eso es todo, entonces, ¿cómo solucionar este problema? El resultado que quiero es 0,1 + 0,2 === 0,3 ¡Ah! ! !
Una de las soluciones más simples es dar requisitos de precisión claros en el proceso de devolución del valor, la computadora redondeará automáticamente, como por ejemplo:
var númA = 0,1;
var número B = 0,2;
alerta( parseFloat((numA + numB).toFixed(2)) === 0.3 );
Pero obviamente este no es un método único. Sería fantástico si existiera un método que pudiera ayudarnos a resolver el problema de precisión de estos números de punto flotante. Probemos este método:
Math.formatFloat = función(f, dígito) {
var m = Math.pow(10, dígito);
devolver parseInt(f * m, 10) / m;
}
var númA = 0,1;
var número B = 0,2;
alerta(Math.formatFloat(numA + numB, 1) === 0.3);
¿Qué significa este método? Para evitar diferencias de precisión, debemos multiplicar el número que se va a calcular por 10 a la enésima potencia, convertirlo en un número entero que la computadora pueda reconocer con precisión y luego dividirlo por 10 a la enésima potencia. Los lenguajes de programación manejan diferencias de precisión, lo usaremos para lidiar con el error de precisión de los números de punto flotante en JS.
Si alguien te pregunta la próxima vez a qué equivale 0,1 + 0,2, ¡debes tener cuidado con tu respuesta! !