内容

名称

bigfloat - Perl 透明大浮点数支持

概要

use bigfloat;

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

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

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

描述

给定作用域中的所有数字字面量都将转换为 Math::BigFloat 对象。

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

因此,以下代码

use bigfloat;
$x = 1234;

创建一个 Math::BigFloat 并将对它的引用存储在 $x 中。这在幕后透明地发生。

您可以使用以下代码查看这一点

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

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

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

(请注意,如果表达式以 '(' 开头,print 的行为与预期不符,因此需要使用 +)

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

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

请注意,以下代码无法按预期工作(不输出任何内容),因为 Perl 中(截至 v5.8.0)尚不支持 '..' 的重载

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

选项

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

a 或 accuracy

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

perl -Mbigfloat=a,50 -le 'print sqrt(20)'

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

p 或 precision

这将设置所有数学运算的精度。参数可以是任何整数。负值表示小数点后固定位数,而正值表示四舍五入到小数点左侧的该位数。0 表示四舍五入到整数。有关详细信息,请参阅 Math::BigInt 的 bfround() 方法。

perl -Mbigfloat=p,-50 -le 'print sqrt(20)'

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

t 或 trace

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

l、lib、try 或 only

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

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

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

oct

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

v 或 version

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

perl -Mbigfloat=v

数学库

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

use bigfloat lib => 'Calc';

您可以使用以下语句更改此设置

use bigfloat lib => 'GMP';

以下代码将首先尝试查找 Math::BigInt::Foo,然后查找 Math::BigInt::Bar,如果这两个库都找不到,则恢复到 Math::BigInt::Calc

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

使用 c<lib> 会在找不到任何指定的库并且 Math::BigInt 回退到默认库之一时发出警告。要抑制此警告,请使用 c<try> 代替

use bigfloat try => 'GMP';

如果您希望代码直接终止而不是回退,请使用only代替。

use bigfloat only => 'GMP';

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

方法调用

由于所有数字现在都是对象,因此您可以使用 Math::BigFloat 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::BigFloat 中的更多详细信息,请参阅文档。

方法

inf()

返回 Math::BigFloat->binf() 的快捷方式。由于 Perl 并不总是正确处理裸字inf,因此很有用。

NaN()

返回 Math::BigFloat->bnan() 的快捷方式。由于 Perl 并不总是正确处理裸字NaN,因此很有用。

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

返回欧拉数e,也称为 exp(1)

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

返回 PI。

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

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

示例

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

返回 PI,达到所需的精度。

示例

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

设置或获取精度。

precision()

设置或获取精度。

round_mode()

设置或获取舍入模式。

div_scale()

设置或获取除法比例。

upgrade()

设置或获取降级类升级到的类(如果有)。将升级类设置为undef以禁用升级。

默认情况下,升级被禁用。

downgrade()

设置或获取升级类降级到的类(如果有)。将降级类设置为undef以禁用降级。

默认情况下,降级被禁用。

in_effect()
use bigfloat;

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

返回当前作用域中是否启用了bigfloat

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

注意事项

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

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

运算符与字面量重载

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

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

例如

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

在默认的 32 位构建中输出0,因为bigfloat 永远不会看到字符串字面量。为了确保表达式中的所有内容都被视为Math::BigFloat 对象,请在表达式中使用字面量数字

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

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

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()

bigfloat 使用可以处理大整数的版本覆盖了这些例程。然而,在 Perl 版本低于 v5.9.4 的情况下,除非您使用两个导入标签“hex”和“oct”明确要求,否则这种情况不会发生——并且它将是全局的,无法在使用no bigfloat 的作用域内禁用。

use bigfloat qw/hex oct/;

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

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

将此与以下内容进行比较

use bigfloat;

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

示例

一些酷炫的命令行示例,让 Python 用户印象深刻;)

perl -Mbigfloat -le 'print sqrt(33)'
perl -Mbigfloat -le 'print 2**255'
perl -Mbigfloat -le 'print 4.5+2**255'
perl -Mbigfloat -le 'print 3/7 + 5/7 + 8/3'
perl -Mbigfloat -le 'print 123->is_odd()'
perl -Mbigfloat -le 'print log(2)'
perl -Mbigfloat -le 'print exp(1)'
perl -Mbigfloat -le 'print 2 ** 0.5'
perl -Mbigfloat=a,65 -le 'print 2 ** 0.2'
perl -Mbigfloat=l,GMP -le 'print 7 ** 7777'

错误

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

支持

您可以使用 perldoc 命令查找此模块的文档。

perldoc bigfloat

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

许可证

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

另请参阅

bigintbigrat

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

作者