Comment désactiver la notation scientifique lorsque je travaille avec de très grands nombres en Perl?

StackOverflow https://stackoverflow.com/questions/1424317

Question

Considérez ce qui suit:

print 3 ** 333; #Yields 7.6098802313206e+158

Ma question est simple: comment désactiver la notation scientifique lorsque je travaille avec de très grands nombres? En gros, j'aimerais voir tous les chiffres transférés dans stdout in extenso.

Est-ce possible?

Était-ce utile?

La solution

Voir Math :: BigInt

use Math::BigInt;
$x = Math::BigInt->new("3");
print $x ** 333;

Sortie:

760988023132059809720425867265032780727896356372077865117010037035791631439306199613044145649378522557935351570949952010001833769302566531786879537190794573523

Autres conseils

Si vous voulez le faire pour tous les entiers de votre programme, vous pouvez simplement ajouter:

use bigint;

Si vous ne voulez le faire que pour certains entiers, vous pouvez créer Math :: BigInt objets.

Il existe également les bignum et Math :: BigNum si vous utilisez des flottants.

Pour les très petites valeurs, voir le code suivant:

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

Avec des nombres aussi gros, vous pouvez avoir plus de chiffres que la précision utilisée pour stocker les nombres. (Voir un exemple simple pouvant être exécuté aurait résolu cette question.)

Si vous avez vraiment besoin de voir les 150 chiffres ou plus, utilisez les modules bigint (pour les entiers), bigrat (pour les nombres rationnels) et bignum (pour les nombres à virgule flottante).

Avait le même problème avec ce code:

#!/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 );
}

Les deux dernières lignes où l’impression:

2 ^   63 = -4611686018427387904 to 4611686018427387904  or -9223372036854775808
2 ^   64 = -9223372036854775808 to -9223372036854775808 or                   -1

Évidemment pas correct, et ne réalisant pas que la conversion% d était la cause du problème, j'ai essayé la solution indiquée ici:

#!/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 );
}

C'est à ce moment-là que j'ai réalisé que la conversion printf 'd' était à l'origine d'un problème. En lisant Math :: BigInt, il semble suggérer que ces nombres sont stockés sous forme de chaînes à l'intérieur. Le passage à une conversion 's' a donc résolu le problème suivant:

#!/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 );
}

Maintenant, les deux dernières lignes imprimées correctement:

2 ^   63 = -4611686018427387904 to 4611686018427387904  or  9223372036854775808
2 ^   64 = -9223372036854775808 to 9223372036854775808  or 18446744073709551616

Mais en ce qui concerne la réponse de Karel, qui était à peu près correcte, à mon humble avis, cela pourrait également être fait sans utiliser BigInt (bigint, BigNum, ...) en utilisant la conversion 'f' mais avec la précision définie sur '0 'éliminer ces nombres décimaux:

#!/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 );
}

Cela fonctionne également pour la question du PO:

perl -e 'printf "%.0f\n", 3 ** 333'
760988023132059813486251563646478824265752535077884574263917414498578085812167738721447369281049109603746001743233145041176969930222526036520619613114171654144
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top