• Publicidad

Perl a la satura

¿Apenas comienzas con Perl? En este foro podrás encontrar y hacer preguntas básicas de Perl con respuestas aptas a tu nivel.

Perl a la satura

Notapor creating021 » 2006-10-23 20:04 @878

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
my $cent = 0.01;
my $total = 0.0;
print "Total $total\n";
for ( my $i = 0; $i < 1000; $i++){
  $total += $cent;
}
print "Ahora tengo $total y deberia ser 1o\n";
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4

:? Y no es el unico lenguaje: C#, Java, COBOL y otros.
Expect the worst, is it the least you can do?
Avatar de Usuario
creating021
Perlero frecuente
Perlero frecuente
 
Mensajes: 595
Registrado: 2006-02-23 16:17 @720
Ubicación: Frente al monitor

Publicidad

Notapor explorer » 2006-10-23 20:45 @906

Es un problema muy viejo de los ordenadores, por la imposibilidad de representar determinados valores en punto flotante.
Ejemplo:
Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
$ perl -le '$#="%.20g"; $x=0.2; print $x'
0.20000000000000001
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4
Ya sólo con almacenar 0.2 estamos cometiendo un error.

En el ejemplo indicado por creating021, lo que ocurre es que estamos acumulando error tras error y por eso al final la diferencia es tan grande.

En un trabajo normal con el ordenador no solemos ver estos problemas porque los programas suelen redondear los cálculos a números con muchos menos dígitos significativos:
Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
$ perl -le '$x=0.2; print $x'
0.2
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


En cambio, saber esto es crucial cuando estamos haciendo muchas operaciones matemáticas y necesitamos obtener una gran precisión.

En Perl contamos con dos módulos que nos pueden ayudar en estas tareas: Integer y Math::BigFloat, que, con unos leves cambios, nos arreglan el problema:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl

use Math::BigFloat;

my $cent  = Math::BigFloat->new(0.01);
my $total = Math::BigFloat->new(0.00);
print "Total $total\n";
for ( my $i = 0; $i < 1000; $i++){
  $total += $cent;
}
print "Ahora tengo $total y deberia ser 10\n";
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Código: Seleccionar todo
Total 0
Ahora tengo 10 y deberia ser 10
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor creating021 » 2006-10-24 15:16 @677

Realmente el problema está cuando multiplicas, sumas, restas o divides un número ya que no estás usando un número si no un numeral.
Tal como lo pone Tom Phoenix en su ejemplo al escribir en Perl Journal:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl -w
use strict;

my $total = 19.08 + 2.01;
my $expected_total = 21.09;

print "The total is \$$total\n";
print "Rhe expected total is \$$expected_total\n";

if($total == $expected_total){
  print "They are equal.\n";
} else {
  print ·They aren't equal.\n";
}
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Suena ilógico, pero así es, la solución es regex o usar sprintfy substr; también se habla de abs de tal forma:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
if (abs($total -$expected_total) < 0.0000001){ ... }
 
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Lo que dice explorer es tambien correcto y mas cuando se usa googoles.
Expect the worst, is it the least you can do?
Avatar de Usuario
creating021
Perlero frecuente
Perlero frecuente
 
Mensajes: 595
Registrado: 2006-02-23 16:17 @720
Ubicación: Frente al monitor


Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 0 invitados

cron