在Perl中使用非常大的数字时如何禁用科学记数法?

时间:2009-09-14 23:02:31

标签: perl formatting integer biginteger numeric

请考虑以下事项:

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

我的问题很简单:在使用非常大的数字时,如何禁用科学记数法?基本上,我希望将所有数字逐字地转储到stdout

这可能吗?

5 个答案:

答案 0 :(得分:15)

请参阅Math::BigInt

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

输出:

760988023132059809720425867265032780727896356372077865117010037035791631439306199613044145649378522557935351570949952010001833769302566531786879537190794573523

答案 1 :(得分:6)

如果要对程序中的所有整数执行此操作,只需添加:

即可
use bigint;

如果您只想对某些整数执行此操作,则可以创建Math::BigInt个对象。

如果你正在使用花车,还有bignumMath::BigNum

答案 2 :(得分: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

答案 3 :(得分:2)

对于数字较大的数字,您可能拥有比用于存储数字的精度更多的数字。 (看到一个简单的可运行的例子就可以解决这个问题。)

如果你真的需要看到所有150多个数字,你应该使用bigint(对于整数),bigrat(对于有理数)和bignum(对于浮点数)模块。

答案 4 :(得分: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 = %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的答案,这几乎是正确的恕我直言,这也可以通过使用'f'转换而不使用BigInt(bigint,BigNum,...)但精度设置为'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