¿Cómo puedo desactivar la notación científica cuando trabajo con números muy grandes en Perl?
-
07-07-2019 - |
Pregunta
Considere lo siguiente:
print 3 ** 333; #Yields 7.6098802313206e+158
Mi pregunta es simple: ¿cómo puedo desactivar la notación científica cuando trabajo con números muy grandes? Básicamente, me gustaría ver todos los dígitos volcados a stdout
textualmente.
¿Es esto posible?
Solución
Ver Math::BigInt
use Math::BigInt;
$x = Math::BigInt->new("3");
print $x ** 333;
Salida:
760988023132059809720425867265032780727896356372077865117010037035791631439306199613044145649378522557935351570949952010001833769302566531786879537190794573523
Otros consejos
Si desea hacerlo para todos los enteros en su programa, simplemente puede agregar:
use bigint;
Si solo desea hacerlo para algunos enteros, puede crear Math :: BigInt objetos.
También hay bignum y Math :: BigNum si está trabajando con flotantes.
Para valores muy pequeños vea el siguiente código:
my $value = 1e-07; # = 0.0000001
# NOPE
print $value; # prints 1e-07, $value is a number
print sprintf("%f", $value); # prints 0, $value is a number
print sprintf("%.10f", $value); # prints 0.0000001000, $value is a number
$value = sprintf("%.10f", $value);
print $value # prints 1e-07, $value is a number
# /NOPE
use bignum;
$value = ($value+0)->bstr();
print $value; # prints 0.0000001, $value is a string
no bignum;
print $value; # prints 0.0000001, $value is a string
# HOORAY
Con números tan grandes puede tener más dígitos que la precisión utilizada para almacenar los números. (Ver un ejemplo ejecutable simple habría resuelto esta pregunta).
Si realmente necesita ver más de 150 dígitos, debe usar los módulos bigint (para enteros), bigrat (para números racionales) y bignum (para números de coma flotante).
Tuve el mismo problema con este código:
#!/usr/bin/perl
use strict;
use warnings;
print "Base Exp MAX Signed-Negitive MAX Signed-Positive MAX Unsigned\n";
for( my $x = 1; $x <= 64; $x++ ) {
my $y = (2 ** $x);
printf( "2 ^ %4d = %20d to %-20d or %20d\n",
$x, $y/-2, $y/2, $y );
}
Las dos últimas líneas donde se imprime:
2 ^ 63 = -4611686018427387904 to 4611686018427387904 or -9223372036854775808
2 ^ 64 = -9223372036854775808 to -9223372036854775808 or -1
Obviamente no está bien, y al no darme cuenta de que la conversión% d estaba causando el problema, probé la solución marcada aquí:
#!/usr/bin/perl
use strict;
use warnings;
use Math::BigInt;
print "Base Exp MAX Signed-Negitive MAX Signed-Positive MAX Unsigned\n";
for( my $x = Math::BigInt->new('1'); $x <= 64; $x++ ) {
my $y = Math::BigInt->new(2 ** $x);
printf( "2 ^ %4d = %20d to %-20d or %20d\n",
$x, $y/-2, $y/2, $y );
}
Fue entonces cuando me di cuenta de que la conversión printf 'd' estaba causando un problema. Leer sobre Math :: BigInt parece sugerir que estos números se almacenan como cadenas dentro, por lo que al cambiar a una conversión 's', se solucionó el problema:
#!/usr/bin/perl
use strict;
use warnings;
use Math::BigInt;
print "Base Exp MAX Signed-Negitive MAX Signed-Positive MAX Unsigned\n";
for( my $x = Math::BigInt->new('1'); $x <= 64; $x++ ) {
my $y = Math::BigInt->new(2 ** $x);
printf( "2 ^ %4s = %20s to %-20s or %20s\n",
$x, $y/-2, $y/2, $y );
}
Ahora las dos últimas líneas impresas correctamente:
2 ^ 63 = -4611686018427387904 to 4611686018427387904 or 9223372036854775808
2 ^ 64 = -9223372036854775808 to 9223372036854775808 or 18446744073709551616
Pero en lo que respecta a la respuesta de Karel, que era casi correcta en mi humilde opinión, esto también podría hacerse sin el uso de BigInt (bigint, BigNum, ...) utilizando la conversión 'f' pero con la precisión establecida en '0 'para eliminar esos decimales:
#!/usr/bin/perl
use strict;
use warnings;
print "Base Exp MAX Signed-Negitive MAX Signed-Positive MAX Unsigned\n";
for( my $x = 1; $x <= 64; $x++ ) {
my $y = (2 ** $x);
printf( "2 ^ %4d = %20.0f to %-20.0f or %20.0f\n",
$x, $y/-2, $y/2, $y );
}
Esto también funciona para la pregunta del OP:
perl -e 'printf "%.0f\n", 3 ** 333'
760988023132059813486251563646478824265752535077884574263917414498578085812167738721447369281049109603746001743233145041176969930222526036520619613114171654144