Как отключить научную нотацию при работе с очень большими числами в 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