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?

Foi útil?

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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top