内容

名称

bigint - Perl 透明大整数支持

概要

use bigint;

$x = 2 + 4.5;                       # Math::BigInt 6
print 2 ** 512;                     # Math::BigInt 134...096
print inf + 42;                     # Math::BigInt inf
print NaN * 7;                      # Math::BigInt NaN
print hex("0x1234567890123490");    # Perl v5.10.0 or later

{
    no bigint;
    print 2 ** 256;                 # a normal Perl scalar now
}

# for older Perls, import into current package:
use bigint qw/hex oct/;
print hex("0x1234567890123490");
print oct("01234567890123490");

描述

给定范围内所有数字字面量都将转换为 Math::BigInt 对象。表示非整数的数字字面量将被截断为整数。所有表达式的结果也将被截断为整数。

所有运算符(包括基本数学运算)除了范围运算符 .. 都被重载。

integer 编译指示不同,bigint 编译指示创建的整数仅受可用内存大小的限制。

因此,以下代码

use bigint;
$x = 1234;

创建一个 Math::BigInt 并将对它的引用存储在 $x 中。这发生在幕后,对您来说是透明的。

你可以通过以下方式看到这一点

perl -Mbigint -le 'print ref(1234)'

由于数字实际上是对象,你可以对它们调用 Math::BigFloat 中的所有常用方法。这在一定程度上甚至适用于表达式

perl -Mbigint -le '$x = 1234; print $x->bdec()'
perl -Mbigint -le 'print 1234->copy()->binc();'
perl -Mbigint -le 'print 1234->copy()->binc->badd(6);'
perl -Mbigint -le 'print +(1234)->copy()->binc()'

(注意,如果表达式以 '(' 开头,print 不会按预期执行,因此需要 +

你甚至可以像往常一样将操作链接在一起

perl -Mbigint -le 'print 1234->copy()->binc->badd(6);'
1241

请注意,以下操作不会按预期执行(不打印任何内容),因为 Perl 中的 '..' 重载尚未实现(截至 v5.8.0)

perl -Mbigint -le 'for (1..2) { print ref($_); }'

use integer vs. use bigint

use integeruse bigint 之间存在一些差异。

use integer 仅限于 Perl 标量可以处理的内容,而 use bigint 可以处理任意大的整数。

此外,use integer 会影响对变量的赋值以及某些函数的返回值。use bigint 会将这些结果截断为整数

# perl -Minteger -wle 'print 3.2'
3.2
# perl -Minteger -wle 'print 3.2 + 0'
3
# perl -Mbigint -wle 'print 3.2'
3
# perl -Mbigint -wle 'print 3.2 + 0'
3

# perl -Mbigint -wle 'print exp(1) + 0'
2
# perl -Mbigint -wle 'print exp(1)'
2
# perl -Minteger -wle 'print exp(1)'
2.71828182845905
# perl -Minteger -wle 'print exp(1) + 0'
2

在实践中,对于较小的整数,这很少会造成影响,因为表达式的部分和结果无论如何都会被截断,但这可能会影响子例程的返回值,例如

sub three_integer { use integer; return 3.2; }
sub three_bigint { use bigint; return 3.2; }

print three_integer(), " ", three_bigint(),"\n";    # prints "3.2 3"

选项

bigint 识别一些选项,这些选项可以在通过 use 加载时传递。以下选项存在

a 或 accuracy

这将设置所有数学运算的精度。参数必须大于或等于零。有关详细信息,请参阅 Math::BigInt 的 bround() 方法。

perl -Mbigint=a,2 -le 'print 12345+1'

请注意,无法同时设置精度和准确度。

p 或 precision

这将设置所有数学运算的精度。参数可以是任何整数。负值表示小数点后的固定位数,并且会被忽略,因为所有操作都在整数空间中进行。正值将四舍五入到小数点左侧的该位数。0 表示四舍五入到整数。有关详细信息,请参阅 Math::BigInt 的 bfround() 方法。

perl -mbigint=p,5 -le 'print 123456789+123'

请注意,无法同时设置精度和准确度。

t 或 trace

这将启用跟踪模式,主要用于调试。

l、lib、try 或 only

加载不同的数学库,请参阅 "数学库"

perl -Mbigint=l,GMP -e 'print 2 ** 512'
perl -Mbigint=lib,GMP -e 'print 2 ** 512'
perl -Mbigint=try,GMP -e 'print 2 ** 512'
perl -Mbigint=only,GMP -e 'print 2 ** 512'
hex

使用可以处理大数字的版本覆盖内置的 hex() 方法。这通过将其导出到当前包来覆盖它。在 Perl v5.10.0 及更高版本中,这不再需要,因为只要 bigint 准则处于活动状态,hex() 就会在当前作用域中被词法覆盖。

oct

用可以处理大数字的版本覆盖内置的 oct() 方法。这通过将其导出到当前包来覆盖它。在 Perl v5.10.0 及更高版本中,这并不那么必要,因为只要bigint pragma 处于活动状态,oct() 就会在当前范围内词法覆盖。

v 或版本

这将打印出模块的名称和版本,然后退出。

perl -Mbigint=v

数学库

数字的数学运算(默认情况下)由名为 Math::BigInt::Calc 的后端库模块完成。默认值等同于说

use bigint lib => 'Calc';

您可以使用以下方法更改此设置

use bigint lib => 'GMP';

以下操作将首先尝试查找 Math::BigInt::Foo,然后查找 Math::BigInt::Bar,如果这也失败,则恢复到 Math::BigInt::Calc

use bigint lib => 'Foo,Math::BigInt::Bar';

如果无法找到指定的库,并且Math::BigInt 回退到默认库之一,则使用 c<lib> 会发出警告。要抑制此警告,请改用 c<try>

use bigint try => 'GMP';

如果您希望代码死亡而不是回退,请改用only

use bigint only => 'GMP';

有关更多详细信息,请参阅各个模块文档。

方法调用

由于所有数字现在都是对象,因此您可以使用 Math::BigInt API 中的所有方法。

但需要发出警告。当使用以下方法复制数字时,只会进行浅层复制。

$x = 9; $y = $x;
$x = $y = 7;

使用复制或原始数字进行重载数学运算是可以的,例如,以下操作有效

$x = 9; $y = $x;
print $x + 1, " ", $y,"\n";     # prints 10 9

但调用任何直接修改数字的方法会导致原始数字和复制数字都被销毁

$x = 9; $y = $x;
print $x->badd(1), " ", $y,"\n";        # prints 10 10

$x = 9; $y = $x;
print $x->binc(1), " ", $y,"\n";        # prints 10 10

$x = 9; $y = $x;
print $x->bmul(2), " ", $y,"\n";        # prints 18 18

使用不修改但测试内容是否有效的方法

$x = 9; $y = $x;
$z = 9 if $x->is_zero();                # works fine

有关复制构造函数和重载中的=,以及 Math::BigInt 中的文档,请参阅文档。

方法

inf()

返回 Math::BigInt->binf() 的快捷方式。因为 Perl 并不总是正确地处理裸词inf,所以很有用。

NaN()

返回 Math::BigInt->bnan() 的快捷方式。因为 Perl 并不总是正确地处理裸词NaN,所以很有用。

e
# perl -Mbigint=e -wle 'print e'

返回欧拉数e,也称为 exp(1)。请注意,在bigint 下,这将被截断为整数,即 2。

PI
# perl -Mbigint=PI -wle 'print PI'

返回 PI。请注意,在bigint 下,这将被截断为整数,即 3。

bexp()
bexp($power, $accuracy);

返回欧拉数 e 乘以适当的幂,达到所需的精度。

请注意,在 bigint 下,结果将被截断为整数。

示例

# perl -Mbigint=bexp -wle 'print bexp(1,80)'
bpi()
bpi($accuracy);

返回 PI 到所需的精度。请注意,在 bigint 下,这将被截断为整数,即 3。

示例

# perl -Mbigint=bpi -wle 'print bpi(80)'
accuracy()

设置或获取精度。

precision()

设置或获取精度。

round_mode()

设置或获取舍入模式。

div_scale()

设置或获取除法比例。

in_effect()
use bigint;

print "in effect\n" if bigint::in_effect;       # true
{
    no bigint;
    print "in effect\n" if bigint::in_effect;   # false
}

如果 bigint 在当前作用域中生效,则返回 true 或 false。

此方法仅适用于 Perl v5.9.4 或更高版本。

注意事项

十六进制、八进制和二进制浮点数字面量

Perl(以及此模块)接受十六进制、八进制和二进制浮点数字面量,但在 Perl v5.32.0 之前的版本中谨慎使用它们,因为某些版本的 Perl 会静默地给出错误的结果。

运算符与字面量重载

bigint 通过重载整数和浮点数字面量的处理来工作,将它们转换为 Math::BigInt 对象。

这意味着仅涉及字符串值或字符串字面量的算术运算将使用 Perl 的内置运算符执行。

例如

use bigint;
my $x = "900000000000000009";
my $y = "900000000000000007";
print $x - $y;

在默认的 32 位构建中输出 0,因为 bigint 从未看到字符串字面量。要确保表达式全部被视为 Math::BigInt 对象,请在表达式中使用字面量数字

print +(0+$x) - $y;
范围

Perl 不允许重载范围,因此您既不能安全地使用具有 bigint 端点的范围,也不能将迭代器变量作为 Math::BigInt

use 5.010;
for my $i (12..13) {
  for my $j (20..21) {
    say $i ** $j;  # produces a floating-point number,
                   # not an object
  }
}
in_effect()

此方法仅适用于 Perl v5.9.4 或更高版本。

hex()/oct()

bigint 用可以处理大整数值的版本覆盖了这些例程。然而,在 Perl v5.9.4 之前的版本中,除非您使用两个导入标签“hex”和“oct”明确要求,否则这不会发生 - 然后它将是全局的,并且不能在使用 no bigint 的作用域内禁用。

use bigint qw/hex oct/;

print hex("0x1234567890123456");
{
    no bigint;
    print hex("0x1234567890123456");
}

对 hex() 的第二次调用将警告非可移植常量。

将此与

use bigint;

# will warn only under Perl older than v5.9.4
print hex("0x1234567890123456");

示例

一些很酷的命令行示例,可以给 Python 人群留下深刻印象 ;) 你可能想将它们与 -Mbigfloat 或 -Mbigrat 下的结果进行比较。

perl -Mbigint -le 'print sqrt(33)'
perl -Mbigint -le 'print 2**255'
perl -Mbigint -le 'print 4.5+2**255'
perl -Mbigint -le 'print 123->is_odd()'
perl -Mbigint=l,GMP -le 'print 7 ** 7777'

错误

请将任何错误或功能请求报告到 bug-bignum at rt.cpan.org,或通过网页界面报告到 https://rt.cpan.org/Ticket/Create.html?Queue=bignum(需要登录)。我们会收到通知,然后你将在我对错误进行更改时自动收到进度通知。

支持

你可以使用 perldoc 命令找到此模块的文档。

perldoc bigint

你也可以在以下位置查找信息:

许可证

本程序是自由软件;你可以根据与 Perl 本身相同的条款重新发布和/或修改它。

另请参阅

bignumbigrat

Math::BigIntMath::BigFloatMath::BigRatMath::Big 以及 Math::BigInt::FastCalcMath::BigInt::PariMath::BigInt::GMP

作者