ddiana escribiste:Hola a todos, tengo un pequeño programa en Perl que debería generar números de 0.01 a 1 aumentando de 0.01 en 0.01. Funciona bien para valores de 0.01 a 0.81 pero después de este valor, en vez de generar 0.82 obtengo 0.820000000001 y no sé de dónde sale ese 0.0000000001 adicional.
La representación que utilizan los ordenadores internamente para manejar números reales es, en general, una aproximación y por lo tanto hay que contar con que al hacer operaciones en punto flotante, estos errores pueden hacerse visibles.
No obstante, ¡eso no quita que podamos minimizar esos errores!
Por ejemplo, en tu caso estás sumando 0.01 (valor que, por cierto, el ordenador no es capaz de representar de manera exacta) a un contador dentro de un bucle. Cada operación introduce nuevos errores en el calculo, por lo que después de ochenta y pico iteraciones el error se hace visible. Al calcular de esa manera estas multiplicando el error inicial.
Una mejor forma de hacerlo es teniendo en cuenta que una suma repetida puede convertirse en una multiplicación:
Using perl Syntax Highlighting
$w0=0;
for ($i=0;$i<=100;$i++)
{
print "omega--> $w \n";
$w=$w0 + $i * 0.01;
}Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4
De esta manera el cálculo de $w se limita siempre a dos operaciones y no se produce la acumulación de errores de la que pecaba tu código.
Otra buena técnica es tratar de realizar las operaciones utilizando números enteros siempre que podamos. En tu caso:
Using perl Syntax Highlighting
$w0=0;
for ($i=0;$i<=100;$i++)
{
print "omega--> $w \n";
$w=$w0 + $i / 100;
}Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4
Por último, en algunas ocasiones (aunque la verdad es que son casos raros), también te puede interesar utilizar alguno de los módulos que hay en CPAN para manejar números racionales como por ejemplo
Math::BigRat. El módulo
Math::BigInt que ya te ha recomendado explorer, también permite hacer operaciones en punto fijo (números racionales con un número predeterminado de decimales) que se emplean a menudo en cálculos financieros donde los redondeos importan mucho.