Como posso desativar notação científica quando se trabalha com números muito grandes em Perl?
-
07-07-2019 - |
Pergunta
Considere o seguinte:
print 3 ** 333; #Yields 7.6098802313206e+158
A minha pergunta é simples: Como posso desativar notação científica quando se trabalha com números muito grandes? Basicamente, eu gostaria de ver todos os dígitos despejado para stdout
verbatim.
Isso é possível?
Solução
Veja Math::BigInt
use Math::BigInt;
$x = Math::BigInt->new("3");
print $x ** 333;
Output:
760988023132059809720425867265032780727896356372077865117010037035791631439306199613044145649378522557935351570949952010001833769302566531786879537190794573523
Outras dicas
Se você quiser fazê-lo para todos os inteiros em seu programa, você pode apenas adicionar:
use bigint;
Se você só quer fazer isso por alguns inteiros, você pode criar Math :: BigInt objetos.
Há também bignum e Math :: bignum se você estiver trabalhando com flutuadores.
Para valores muito pequenos ver o seguinte 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
Com números tão grande que você pode ter mais dígitos do que a precisão usado para armazenar os números. (Ver um exemplo executável simples teria resolvido esta questão).
Se você realmente precisa para ver todos os 150+ dígitos, você deve usar o bigint (para inteiros), bigrat (para números racionais) eo bignum (para números de ponto flutuante) módulos.
tive o mesmo problema com 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 );
}
As duas últimas linhas, onde a impressão:
2 ^ 63 = -4611686018427387904 to 4611686018427387904 or -9223372036854775808
2 ^ 64 = -9223372036854775808 to -9223372036854775808 or -1
Obviamente não é certo, e não realizando a conversão% d estava causando o problema, eu tentei a solução sinalizado aqui:
#!/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 );
}
Foi quando eu percebi que o printf 'd' conversão estava causando um problema. Lendo sobre Math :: BigInt parece sugerir que esses números são armazenados como strings dentro, mudando assim a uma conversão 's', corrigiu o 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 );
}
Agora, as duas últimas linhas impressos corretamente:
2 ^ 63 = -4611686018427387904 to 4611686018427387904 or 9223372036854775808
2 ^ 64 = -9223372036854775808 to 9223372036854775808 or 18446744073709551616
Mas no que diz respeito à resposta de Karel, que era IMHO quase correta, isso também poderia ser feito sem o uso de BigInt (bigint, bignum, ...) usando a conversão 'f', mas com o conjunto de precisão para '0 'para eliminar os decimais:
#!/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 );
}
Isso também funciona para a pergunta do OP:
perl -e 'printf "%.0f\n", 3 ** 333'
760988023132059813486251563646478824265752535077884574263917414498578085812167738721447369281049109603746001743233145041176969930222526036520619613114171654144