目錄

名稱

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 pragma 不同,bigint pragma 建立的整數大小只受限於可用的記憶體。

因此,以下程式碼

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 與 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 或準確度

這會設定所有數學運算的準確度。引數必須大於或等於零。請參閱 Math::BigInt 的 bround() 方法以取得詳細資料。

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

請注意,無法同時設定精度和準確度。

p 或精度

這會設定所有數學運算的精度。引數可以是任何整數。負值表示小數點後固定位數,且會被忽略,因為所有運算都在整數空間中進行。正值會從小數點左邊四捨五入到此位數。0 表示四捨五入為整數。請參閱 Math::BigInt 的 bfround() 方法以取得詳細資料。

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

請注意,無法同時設定精度和準確度。

t 或追蹤

這會啟用追蹤模式,主要用於除錯。

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 函式庫

預設情況下,數字的運算會由後端函式庫模組 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';

如果找不到任何指定的函式庫,則使用 c<lib> 會發出警告,而 Math::BigInt 會回退至其中一個預設函式庫。若要抑制此警告,請改用 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(和此模組)接受十六進位、八進位和二進位浮點數字面量,但在 v5.32.0 之前的 Perl 版本中使用時請小心,因為某些 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 5.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

作者