• Publicidad

Números mayores de 16 dígitos

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

Números mayores de 16 dígitos

Notapor FluiD » 2010-04-27 15:11 @674

Creo que es algo absurdo (como mi nivel de Perl) pero el siguiente código ¿por qué "dispara" números de este tipo: 8.00000000002417e+15 cuando la longitud de los dígitos es 16 y cuando es menor lo hace correctamente?

El bucle es solo a modo de ejemplo:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
for ($i=8000000000000000;$i != 9000000000000000;$i++)
   {
      print "$i\n";
   }
 
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


Necesitaría que la salida fuera con la longitud correcta para mi propósito.

No sé si influye el SO pero estoy en Ubuntu con el intérprete 5.10.0.

Saludos.

MiG.G
FluiD
Perlero nuevo
Perlero nuevo
 
Mensajes: 14
Registrado: 2009-10-16 14:38 @651

Publicidad

Re: Números mayores de 16 dígitos

Notapor hreyes » 2010-04-27 15:56 @705

Podrías intentar esto:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
for ($i=8000000000000000;$i != 9000000000000000;$i++)
   {
            $numero = sprintf("%f\n",$i);
            print $numero;
   }
 
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


y te dará números de este estilo:

Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
8000000000234558.000000
8000000000234559.000000
8000000000234560.000000
8000000000234561.000000
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4
hreyes
Perlero nuevo
Perlero nuevo
 
Mensajes: 3
Registrado: 2010-04-27 15:52 @703

Re: Números mayores de 16 dígitos

Notapor FluiD » 2010-04-27 16:18 @721

Gracias, la verdad es que mejora bastante, pero ¿cómo podría quitar la parte decimal?

Saludos.

MiG.G
FluiD
Perlero nuevo
Perlero nuevo
 
Mensajes: 14
Registrado: 2009-10-16 14:38 @651

Re: Números mayores de 16 dígitos

Notapor explorer » 2010-04-27 17:02 @751

Bienvenido a los foros de Perl en Español, hreyes.

Perl es un poco especial en el trabajo con números... solo hay que leer perlnumber o bignum.

A veces hace cosas raras...

En mi máquina, que es un 64 bits, no tengo problemas para representar números de hasta 19 dígitos:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use 5.010;
  3.  
  4. my $i = 18_446_744_073_709_551_606; # 2**64 -10
  5.  
  6. for (0..19) {
  7.     say $i++;
  8. }
  9. __END__
  10. 18446744073709551606
  11. 18446744073709551607
  12. 18446744073709551608
  13. 18446744073709551609
  14. 18446744073709551610
  15. 18446744073709551611
  16. 18446744073709551612
  17. 18446744073709551613
  18. 18446744073709551614
  19. 18446744073709551615
  20. 1.84467440737096e+19
  21. 1.84467440737096e+19
  22. 1.84467440737096e+19
  23. 1.84467440737096e+19
  24. 1.84467440737096e+19
  25. 1.84467440737096e+19
  26. 1.84467440737096e+19
  27. 1.84467440737096e+19
  28. 1.84467440737096e+19
  29. 1.84467440737096e+19
  30.  
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Aquí, solo hacemos la operación matemática de incrementar. En cuanto superamos el límite de 2**64-1, lo convierte a punto flotante. Lo mismo si hubiera realizado cualquier otra operación matemática, como por ejemplo,
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use 5.010;
  3.  
  4. my $i = 2**64 -10;
  5.  
  6. for (0..19) {
  7.     say $i++;
  8. }
  9.  
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Deberíamos tener la misma salida, pero no es así: la salida es solo de enteros si es de menos de 16 dígitos.

La solución, de momento, es la que te comenta hreyes. Con printf o sprintf y con "%.0f" sacamos las cifras sin la parte decimal.

Si necesitas manejar cifras más grandes (pero muy, muy, muy grandes), puedes usar bignum, que a su vez cargará Math::BigFloat y Math::BigInt. Serán los cálculos un poco más lentos, pero podrás manejar números muy largos.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Números mayores de 16 dígitos

Notapor FluiD » 2010-04-28 01:39 @111

Muchas gracias, explorer. Con bignum va perfecto.

Saludos.

MiG.G
FluiD
Perlero nuevo
Perlero nuevo
 
Mensajes: 14
Registrado: 2009-10-16 14:38 @651

Re: Números mayores de 16 dígitos

Notapor FluiD » 2010-04-28 16:49 @742

Me surge un nuevo problema relacionado. bignum me permite usar números muy grandes pero a costa de una bajada de rendimiento terrible en el manejo de estos. El script básicamente hace un bucle dependiendo de unos valores de entrada y mediante unas condiciones escribe su salida en archivos, y necesito fluidez por encima de todo.

Valores por encima de longitud 16 es poco probable que se usen, entonces, la idea era cargar el módulo bignum si realmente lo necesito, pero si meto el use bignum en un if() que compruebe la longitud del número (esto fuera del bucle antes de empezar los cálculos) dentro de la función que hace todo esto, no funciona. En la ayuda de bignum me dice que hay que cargarlo al principio del script. la pregunta es ¿se puede cargar un módulo justo antes de usarlo, si realmente lo necesito?

Saludos.

MiG.G
FluiD
Perlero nuevo
Perlero nuevo
 
Mensajes: 14
Registrado: 2009-10-16 14:38 @651

Re: Números mayores de 16 dígitos

Notapor explorer » 2010-04-28 17:02 @751

Si no van a superar los 16 dígitos, puedes hacer lo que se te ha comentado antes: trabajas con el número de forma normal, y a la hora de sacarlo en pantalla, usas el printf con el formato "%.0f".

En cuanto a la carga de módulos de forma condicional, puedes usar require() en lugar de use(). La diferencia es en el momento de ejecutarse estas instrucciones. Uno será en tiempo de ejecución y el otro, en el de compilación.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Números mayores de 16 dígitos

Notapor FluiD » 2010-04-29 18:04 @794

Gracias, explorer, por tu tiempo. He estado leyendo algo sobre require y use, y en principio debería funcionar con require, pero solo funciona con use.

Este bucle (a modo de ejemplo):
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
require bignum;

for ($i=1000000000000000; $i != 2000000000000000; $i++)
   {
      print "$i\n"
   }
 
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Sigue "disparando" números en notación científica, y si cambio require por use funciona perfecto. La idea, como dije en mensajes anteriores, es meter la carga del módulo en un if(), de tal modo que "si longitud > 15, carga módulo".

A ver, explorer, si se te ocurre algo, que ando muy pegao con esto.

Saludos y mil graciassss.

MiG.G
FluiD
Perlero nuevo
Perlero nuevo
 
Mensajes: 14
Registrado: 2009-10-16 14:38 @651

Re: Números mayores de 16 dígitos

Notapor explorer » 2010-04-29 18:09 @798

Pero, ¿no lo consigues con el printf "%.0f"?

Actualización: he probado ese bucle en mi ordenador y con el Perl v5.10 sigue saliendo bien.

Si le meto una variación, con una operación matemática que le obligue a pasar el número a punto flotante, entonces sí que sale en notación científica. Pero entonces cambio print() por printf("%.0f\n", $i) y sale perfecto.
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. for (my $i=1000000000000000; $i <= 2000000000000000; $i+= 100000000000000.1) {
  3.     printf "%.0f\n", $i;
  4. }
  5. __END__
  6. 1000000000000000
  7. 1100000000000000
  8. 1200000000000000
  9. 1300000000000000
  10. 1400000000000000
  11. 1500000000000000
  12. 1600000000000000
  13. 1700000000000000
  14. 1800000000000000
  15. 1900000000000000
  16.  
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Actualización 2: He construido esto, que parece que funciona:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use common::sense;
  3. use open 'locale';
  4.  
  5. my $número_gordo = 1746545455554699123456;
  6. my $largo = length $número_gordo;
  7.  
  8. say "$número_gordo, $largo";
  9.  
  10. if ($largo > 16  or  $número_gordo =~ /e/) {
  11.     require Math::BigInt;
  12.     say 'Sí';
  13.     $número_gordo = Math::BigInt->new('1746545455554699123456');
  14. }
  15.  
  16. say $número_gordo;
  17.  
  18.  
  19. __END__
  20. 1.7465454555547e+21, 19
  21. 1746545455554699123456
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Si el número grande supera las 16 cifras o contiene una 'e' (notación científica), cargamos el módulo y lo pasamos a objeto Math::BigInt.

A propósito, en la documentación de Math::BigInt comentan que existe la versión con librería en C, para obtener mayor velocidad, instalando el módulo Math::BigInt::GMP.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Números mayores de 16 dígitos

Notapor explorer » 2010-04-29 18:59 @833

FluiD escribiste:El script básicamente hace un bucle dependiendo de unos valores de entrada y mediante unas condiciones escribe su salida en archivos, y necesito fluidez por encima de todo.

¿No puedes poner un ejemplo de lo que quieres hacer?
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Siguiente

Volver a Básico

¿Quién está conectado?

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