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?

È stato utile?

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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top