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

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

Вопрос

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

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

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

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

Это было полезно?

Решение

Видишь Math::BigInt

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

Выходной сигнал:

760988023132059809720425867265032780727896356372077865117010037035791631439306199613044145649378522557935351570949952010001833769302566531786879537190794573523

Другие советы

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

use bigint;

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

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

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

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

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

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

У меня была та же проблема с этим кодом:

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

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

perl -e 'printf "%.0f\n", 3 ** 333'
760988023132059813486251563646478824265752535077884574263917414498578085812167738721447369281049109603746001743233145041176969930222526036520619613114171654144
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top