考虑以下:
print 3 ** 333; #Yields 7.6098802313206e+158
我的问题很简单:在处理非常大的数字时如何禁用科学记数法?基本上,我希望看到所有数字都被stdout
逐字逐句转储。
这可能吗?
考虑以下:
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
但是关于 Karel 的回答,恕我直言,这几乎是正确的,这也可以在不使用 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