Как отключить научную нотацию при работе с очень большими числами в Perl?

Рассмотрим следующее:

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

Мой вопрос прост: как я могу отключить научную нотацию при работе с очень большими числами? В принципе, я хотел бы видеть все цифры, сбрасываемые до stdout verbatim.

Возможно ли это?

Ответ 1

См. Math::BigInt

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

Вывод:

760988023132059809720425867265032780727896356372077865117010037035791631439306199613044145649378522557935351570949952010001833769302566531786879537190794573523

Ответ 2

Если вы хотите сделать это для всех целых чисел в своей программе, вы можете просто добавить:

use bigint;

Если вы хотите сделать это только для некоторых целых чисел, вы можете создать объекты Math:: BigInt.

Существует также bignum и Math:: BigNum если вы работаете с поплавками.

Ответ 3

Для очень малых значений см. следующий код:

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

Ответ 4

С числами, которые могут быть большими, у вас может быть больше цифр, чем точность, используемая для хранения чисел. (Увидев простой пример выполнения, этот вопрос разрешил бы).

Если вам действительно нужно увидеть все 150 + цифр, вы должны использовать bigint (для целых чисел), bigrat (для рациональных чисел) и модули bignum (для чисел с плавающей запятой).

Ответ 5

Имел ту же проблему с этим кодом:

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

Последние две строки, в которых выполняется печать:

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

Очевидно, что неправильно, и не осознавая, что преобразование% d вызывало проблему, я попробовал решение, помеченное здесь:

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

Это, когда я понял, что преобразование printf 'd' вызывает проблему. Чтение в Math:: BigInt, похоже, предполагает, что эти числа хранятся в виде строк внутри, поэтому переход к 's' конверсии устраняет проблему:

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

Теперь две последние строки напечатаны правильно:

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

Но в отношении ответа Карела, который был почти правильным ИМХО, это также можно было сделать без использования BigInt (bigint, BigNum,...) с использованием преобразования "f", но с точностью, установленной на "0" 'для устранения этих десятичных знаков:

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

Это также работает для вопроса OP:

perl -e 'printf "%.0f\n", 3 ** 333'
760988023132059813486251563646478824265752535077884574263917414498578085812167738721447369281049109603746001743233145041176969930222526036520619613114171654144