Come posso disabilitare la notazione scientifica quando lavoro con numeri molto grandi in Perl?
-
07-07-2019 - |
Domanda
Considera quanto segue:
print 3 ** 333; #Yields 7.6098802313206e+158
La mia domanda è semplice: come posso disabilitare la notazione scientifica quando lavoro con numeri molto grandi? Fondamentalmente, vorrei vedere tutte le cifre scaricate su stdout
alla lettera.
È possibile?
Soluzione
Vedi Math::BigInt
use Math::BigInt;
$x = Math::BigInt->new("3");
print $x ** 333;
Output:
760988023132059809720425867265032780727896356372077865117010037035791631439306199613044145649378522557935351570949952010001833769302566531786879537190794573523
Altri suggerimenti
Se vuoi farlo per tutti i numeri interi nel tuo programma, puoi semplicemente aggiungere:
use bigint;
Se vuoi farlo solo per alcuni numeri interi, puoi creare Math :: BigInt oggetti.
Esistono anche bignum e Math :: BigNum se lavori con float.
Per valori molto piccoli, consultare il codice seguente:
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 numeri così grandi potresti avere più cifre della precisione usata per memorizzare i numeri. (Vedere un semplice esempio eseguibile avrebbe risolto questa domanda).
Se hai davvero bisogno di vedere tutte le oltre 150 cifre, dovresti usare i moduli bigint (per numeri interi), bigrat (per numeri razionali) e bignum (per numeri in virgola mobile).
Ha avuto lo stesso problema con questo codice:
#!/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 );
}
Le ultime due righe in cui stampare:
2 ^ 63 = -4611686018427387904 to 4611686018427387904 or -9223372036854775808
2 ^ 64 = -9223372036854775808 to -9223372036854775808 or -1
Ovviamente non è corretto, e non rendendomi conto che la conversione in% d stava causando il problema, ho provato la soluzione contrassegnata qui:
#!/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 );
}
Fu allora che mi resi conto che la conversione di printf 'd' stava causando un problema. Leggendo sulla matematica :: BigInt sembra suggerire che questi numeri siano memorizzati come stringhe all'interno, quindi cambiando in una "s" conversione, risolto il 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 );
}
Ora le ultime due righe sono state stampate correttamente:
2 ^ 63 = -4611686018427387904 to 4611686018427387904 or 9223372036854775808
2 ^ 64 = -9223372036854775808 to 9223372036854775808 or 18446744073709551616
Ma per quanto riguarda la risposta di Karel, che era quasi corretta IMHO, questo potrebbe anche essere fatto senza l'uso di BigInt (bigint, BigNum, ...) usando la conversione 'f' ma con la precisione impostata su '0 "per eliminare quei decimali:
#!/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 );
}
Questo funziona anche per la domanda del PO:
perl -e 'printf "%.0f\n", 3 ** 333'
760988023132059813486251563646478824265752535077884574263917414498578085812167738721447369281049109603746001743233145041176969930222526036520619613114171654144