[Spanish] El misterio del error de precisión de los números de punto flotante

Finalmente he podido entender el misterio del error de precisión de los números de punto flotante que afecta a todos los lenguajes de programación. Para explicarlo, voy a emular el trabajo que realiza el computador para almacenar y leer el número decimal 0.1

Como los computadores almacenan todos los números y caracteres en binario, el primer paso es transformar el número decimal 0.1 a su representación binaria. Para ello se sigue un algoritmo sencillo:

1) Se toma el número a transformar y se multiplica por 2:

0.1 * 2 = 0.2

2) Se separa la parte entera de la decimal del valor resultante

La parte entera de 0.2 es 0
La parte decimal de 0.2 es 0.2

3) La parte entera se toma como el primer dígito significativo del número binario

0.0______

3) Se repiten los pasos 1 y 2 usando la parte decimal obtenida del paso anterior.

Este proceso se repite hasta que el resultado de sea cero o se obtenga una secuencia periódica.

Si ejecutamos este proceso completo para el número 0.1 obtenemos lo siguiente:

0.1 * 2 = 0.2 -> 0
0.2 * 2 = 0.4 -> 0
0.4 * 2 = 0.8 -> 0
0.8 * 2 = 1.6 -> 1
0.6 * 2 = 1.2 -> 1
0.2 * 2 = 0.4 -> 0 (vuelve a reiniciarse la secuencia)

Con esto obtenemos que la representación binaria de 0.1 es:

0.00011... periódico

Como las computadoras tienen una cantidad finita de bits para almacenar cualquier número, los números periódicos se almacenarán truncados. Si asumimos que nuestra computadora solo almacena el valor 0.00011 y no 0.000110011001100110011... (hasta el infinito), la conversión de binario a decimal de este número sería:

0.00011 = 1/16 + 1/32 = 0.09375

Y con esto hemos comprobado cómo surge un problema de precisión pues 0.1 no es igual a 0.09375, es solo un valor aproximado.

7 thoughts on “[Spanish] El misterio del error de precisión de los números de punto flotante”

  1. De acuerdo. Así es. Y en todo caso si el computador fuera decimal, la memoria de longitud fija finita hace perder precisión. Ejemplo: la expresión de la raiz de 2 es una serie infinita o tiene infinitos numeros en su parte decimal imposibles de registrar en un computador.

  2. Por eso existen los métodos numéricos que tratan de minizar el efecto del control por redondeo y en muchos casos son métodos que en lugar de calcular directamente van produciendo aproximaciones a la respuesta cada vez mejores a medida que aumentan las iteraciones.

    1. Yo llegué a descubrir este error de precisión trabajando con Javascript, en alguna parte del código tenía una comparación simple del tipo if(a==b) que fallaba inexplicablemente

      1. Para evitar la posibilidad de error en comparaciones numéricas de igual, siempre se encontrará o es necesario algún truco. Ejemplo: En lugar de a=0, se compara a< 10^-7 o el numero conveniente que no supere la precisión del computador. Pero podría funcionar mal si por error o cálculo a no es positivo, en cuyo caso tendría que tener algo como 0<ab, en lugar de a=b, diría a-b<10^-7. Esos casos posibles requieren ingenio adicional. Cada caso puede ser diferente. Problemas podrían evitarse utilizando la función valor absoluto. En lugar de a=b estudiar abs(a-b)< 10^-7 por ejemplo

  3. Así es. por eso los algoritmos numéricos se diseñan para controlar y corregir el error por redondeo, mas es inevitable en general. Se habla de estabilidad cuando el algoritmo controla al máximo el error por redondeo y condición del problema que significa que un problema mal condicionado podría reventar aun ante un “algoritmo” estable.

So, what do you think?

This site uses Akismet to reduce spam. Learn how your comment data is processed.