内容

名称

Math::BigInt - 任意大小整数数学包

概要

use Math::BigInt;

# or make it faster with huge numbers: install (optional)
# Math::BigInt::GMP and always use (it falls back to
# pure Perl if the GMP library is not installed):
# (See also the L<MATH LIBRARY> section!)

# to warn if Math::BigInt::GMP cannot be found, use
use Math::BigInt lib => 'GMP';

# to suppress the warning if Math::BigInt::GMP cannot be found, use
# use Math::BigInt try => 'GMP';

# to die if Math::BigInt::GMP cannot be found, use
# use Math::BigInt only => 'GMP';

# Configuration methods (may be used as class methods and instance methods)

Math::BigInt->accuracy();     # get class accuracy
Math::BigInt->accuracy($n);   # set class accuracy
Math::BigInt->precision();    # get class precision
Math::BigInt->precision($n);  # set class precision
Math::BigInt->round_mode();   # get class rounding mode
Math::BigInt->round_mode($m); # set global round mode, must be one of
                              # 'even', 'odd', '+inf', '-inf', 'zero',
                              # 'trunc', or 'common'
Math::BigInt->config();       # return hash with configuration

# Constructor methods (when the class methods below are used as instance
# methods, the value is assigned the invocand)

$x = Math::BigInt->new($str);             # defaults to 0
$x = Math::BigInt->new('0x123');          # from hexadecimal
$x = Math::BigInt->new('0b101');          # from binary
$x = Math::BigInt->from_hex('cafe');      # from hexadecimal
$x = Math::BigInt->from_oct('377');       # from octal
$x = Math::BigInt->from_bin('1101');      # from binary
$x = Math::BigInt->from_base('why', 36);  # from any base
$x = Math::BigInt->from_base_num([1, 0], 2);  # from any base
$x = Math::BigInt->bzero();               # create a +0
$x = Math::BigInt->bone();                # create a +1
$x = Math::BigInt->bone('-');             # create a -1
$x = Math::BigInt->binf();                # create a +inf
$x = Math::BigInt->binf('-');             # create a -inf
$x = Math::BigInt->bnan();                # create a Not-A-Number
$x = Math::BigInt->bpi();                 # returns pi

$y = $x->copy();        # make a copy (unlike $y = $x)
$y = $x->as_int();      # return as a Math::BigInt
$y = $x->as_float();    # return as a Math::BigFloat
$y = $x->as_rat();      # return as a Math::BigRat

# Boolean methods (these don't modify the invocand)

$x->is_zero();          # if $x is 0
$x->is_one();           # if $x is +1
$x->is_one("+");        # ditto
$x->is_one("-");        # if $x is -1
$x->is_inf();           # if $x is +inf or -inf
$x->is_inf("+");        # if $x is +inf
$x->is_inf("-");        # if $x is -inf
$x->is_nan();           # if $x is NaN

$x->is_positive();      # if $x > 0
$x->is_pos();           # ditto
$x->is_negative();      # if $x < 0
$x->is_neg();           # ditto

$x->is_odd();           # if $x is odd
$x->is_even();          # if $x is even
$x->is_int();           # if $x is an integer

# Comparison methods

$x->bcmp($y);           # compare numbers (undef, < 0, == 0, > 0)
$x->bacmp($y);          # compare absolutely (undef, < 0, == 0, > 0)
$x->beq($y);            # true if and only if $x == $y
$x->bne($y);            # true if and only if $x != $y
$x->blt($y);            # true if and only if $x < $y
$x->ble($y);            # true if and only if $x <= $y
$x->bgt($y);            # true if and only if $x > $y
$x->bge($y);            # true if and only if $x >= $y

# Arithmetic methods

$x->bneg();             # negation
$x->babs();             # absolute value
$x->bsgn();             # sign function (-1, 0, 1, or NaN)
$x->bnorm();            # normalize (no-op)
$x->binc();             # increment $x by 1
$x->bdec();             # decrement $x by 1
$x->badd($y);           # addition (add $y to $x)
$x->bsub($y);           # subtraction (subtract $y from $x)
$x->bmul($y);           # multiplication (multiply $x by $y)
$x->bmuladd($y,$z);     # $x = $x * $y + $z
$x->bdiv($y);           # division (floored), set $x to quotient
                        # return (quo,rem) or quo if scalar
$x->btdiv($y);          # division (truncated), set $x to quotient
                        # return (quo,rem) or quo if scalar
$x->bmod($y);           # modulus (x % y)
$x->btmod($y);          # modulus (truncated)
$x->bmodinv($mod);      # modular multiplicative inverse
$x->bmodpow($y,$mod);   # modular exponentiation (($x ** $y) % $mod)
$x->bpow($y);           # power of arguments (x ** y)
$x->blog();             # logarithm of $x to base e (Euler's number)
$x->blog($base);        # logarithm of $x to base $base (e.g., base 2)
$x->bexp();             # calculate e ** $x where e is Euler's number
$x->bnok($y);           # x over y (binomial coefficient n over k)
$x->buparrow($n, $y);   # Knuth's up-arrow notation
$x->backermann($y);     # the Ackermann function
$x->bsin();             # sine
$x->bcos();             # cosine
$x->batan();            # inverse tangent
$x->batan2($y);         # two-argument inverse tangent
$x->bsqrt();            # calculate square root
$x->broot($y);          # $y'th root of $x (e.g. $y == 3 => cubic root)
$x->bfac();             # factorial of $x (1*2*3*4*..$x)
$x->bdfac();            # double factorial of $x ($x*($x-2)*($x-4)*...)
$x->btfac();            # triple factorial of $x ($x*($x-3)*($x-6)*...)
$x->bmfac($k);          # $k'th multi-factorial of $x ($x*($x-$k)*...)

$x->blsft($n);          # left shift $n places in base 2
$x->blsft($n,$b);       # left shift $n places in base $b
                        # returns (quo,rem) or quo (scalar context)
$x->brsft($n);          # right shift $n places in base 2
$x->brsft($n,$b);       # right shift $n places in base $b
                        # returns (quo,rem) or quo (scalar context)

# Bitwise methods

$x->band($y);           # bitwise and
$x->bior($y);           # bitwise inclusive or
$x->bxor($y);           # bitwise exclusive or
$x->bnot();             # bitwise not (two's complement)

# Rounding methods
$x->round($A,$P,$mode); # round to accuracy or precision using
                        # rounding mode $mode
$x->bround($n);         # accuracy: preserve $n digits
$x->bfround($n);        # $n > 0: round to $nth digit left of dec. point
                        # $n < 0: round to $nth digit right of dec. point
$x->bfloor();           # round towards minus infinity
$x->bceil();            # round towards plus infinity
$x->bint();             # round towards zero

# Other mathematical methods

$x->bgcd($y);            # greatest common divisor
$x->blcm($y);            # least common multiple

# Object property methods (do not modify the invocand)

$x->sign();              # the sign, either +, - or NaN
$x->digit($n);           # the nth digit, counting from the right
$x->digit(-$n);          # the nth digit, counting from the left
$x->length();            # return number of digits in number
($xl,$f) = $x->length(); # length of number and length of fraction
                         # part, latter is always 0 digits long
                         # for Math::BigInt objects
$x->mantissa();          # return (signed) mantissa as a Math::BigInt
$x->exponent();          # return exponent as a Math::BigInt
$x->parts();             # return (mantissa,exponent) as a Math::BigInt
$x->sparts();            # mantissa and exponent (as integers)
$x->nparts();            # mantissa and exponent (normalised)
$x->eparts();            # mantissa and exponent (engineering notation)
$x->dparts();            # integer and fraction part
$x->fparts();            # numerator and denominator
$x->numerator();         # numerator
$x->denominator();       # denominator

# Conversion methods (do not modify the invocand)

$x->bstr();         # decimal notation, possibly zero padded
$x->bsstr();        # string in scientific notation with integers
$x->bnstr();        # string in normalized notation
$x->bestr();        # string in engineering notation
$x->bfstr();        # string in fractional notation

$x->to_hex();       # as signed hexadecimal string
$x->to_bin();       # as signed binary string
$x->to_oct();       # as signed octal string
$x->to_bytes();     # as byte string
$x->to_base($b);    # as string in any base
$x->to_base_num($b);   # as array of integers in any base

$x->as_hex();       # as signed hexadecimal string with prefixed 0x
$x->as_bin();       # as signed binary string with prefixed 0b
$x->as_oct();       # as signed octal string with prefixed 0

# Other conversion methods

$x->numify();           # return as scalar (might overflow or underflow)

描述

Math::BigInt 提供对任意精度整数的支持。还为 Perl 运算符提供重载。

输入

这些例程的输入值可以是任何标量数字或字符串,这些数字或字符串看起来像数字并表示整数。任何被 Perl 接受为文字数字常量的都应该被此模块接受,除了有限的非整数返回 NaN。

一些有效字符串输入的示例

Input string                Resulting value

123                         123
1.23e2                      123
12300e-2                    123

67_538_754                  67538754
-4_5_6.7_8_9e+0_1_0         -4567890000000

0x13a                       314
0x13ap0                     314
0x1.3ap+8                   314
0x0.00013ap+24              314
0x13a000p-12                314

0o472                       314
0o1.164p+8                  314
0o0.0001164p+20             314
0o1164000p-10               314

0472                        472     Note!
01.164p+8                   314
00.0001164p+20              314
01164000p-10                314

0b100111010                 314
0b1.0011101p+8              314
0b0.00010011101p+12         314
0b100111010000p-3           314

作为标量数字给出的输入可能会丢失精度。引用您的输入以确保没有数字丢失

$x = Math::BigInt->new( 56789012345678901234 );   # bad
$x = Math::BigInt->new('56789012345678901234');   # good

目前,Math::BigInt-new()>(无输入参数)和 Math::BigInt-new("")> 返回 0。这在将来可能会改变,因此始终使用以下显式形式来获取零

$zero = Math::BigInt->bzero();

输出

输出值通常是 Math::BigInt 对象。

布尔运算符 is_zero()is_one()is_inf() 等返回真或假。

比较运算符 bcmp()bacmp()) 返回 -1、0、1 或 undef。

方法

配置方法

以下每个方法(除了 config()、accuracy() 和 precision())都接受三个额外的参数。这些参数 $A$P$R 分别是 accuracyprecisionround_mode。有关更多信息,请参阅有关 "精度和精度" 的部分。

设置类变量会影响之后创建的所有对象实例。

accuracy()
Math::BigInt->accuracy(5);      # set class accuracy
$x->accuracy(5);                # set instance accuracy

$A = Math::BigInt->accuracy();  # get class accuracy
$A = $x->accuracy();            # get instance accuracy

设置或获取精度,即有效数字的数量。精度必须是整数。如果精度设置为 undef,则不进行舍入。

或者,可以使用 "round()""bround()""bfround()" 显式地对结果进行四舍五入,或者将所需的精度作为附加参数传递给方法。

my $x = Math::BigInt->new(30000);
my $y = Math::BigInt->new(7);
print scalar $x->copy()->bdiv($y, 2);               # prints 4300
print scalar $x->copy()->bdiv($y)->bround(2);       # prints 4300

有关详细信息,请参阅关于 "精度和精度" 的部分。

$y = Math::BigInt->new(1234567);    # $y is not rounded
Math::BigInt->accuracy(4);          # set class accuracy to 4
$x = Math::BigInt->new(1234567);    # $x is rounded automatically
print "$x $y";                      # prints "1235000 1234567"

print $x->accuracy();       # prints "4"
print $y->accuracy();       # also prints "4", since
                            #   class accuracy is 4

Math::BigInt->accuracy(5);  # set class accuracy to 5
print $x->accuracy();       # prints "4", since instance
                            #   accuracy is 4
print $y->accuracy();       # prints "5", since no instance
                            #   accuracy, and class accuracy is 5

注意:每个类都有自己的全局变量,与 Math::BigInt 分开,但可以子类化 Math::BigInt 并使子类的全局变量成为 Math::BigInt 中全局变量的别名。

precision()
Math::BigInt->precision(-2);     # set class precision
$x->precision(-2);               # set instance precision

$P = Math::BigInt->precision();  # get class precision
$P = $x->precision();            # get instance precision

设置或获取精度,即相对于小数点的四舍五入位置。精度必须是整数。将精度设置为 $P 表示每个数字向上或向下舍入(取决于舍入模式),舍入到最接近的 10**$P 的倍数。如果精度设置为 undef,则不进行舍入。

您可能希望使用 "accuracy()"。使用 "accuracy()",您可以设置每个结果应具有的位数,而使用 "precision()",您可以设置舍入的位置。

有关详细信息,请参阅关于 "精度和精度" 的部分。

$y = Math::BigInt->new(1234567);    # $y is not rounded
Math::BigInt->precision(4);         # set class precision to 4
$x = Math::BigInt->new(1234567);    # $x is rounded automatically
print $x;                           # prints "1230000"

注意:每个类都有自己的全局变量,与 Math::BigInt 分开,但可以子类化 Math::BigInt 并使子类的全局变量成为 Math::BigInt 中全局变量的别名。

div_scale()

设置/获取回退精度。当未显式设置精度或精度时,使用此精度。当计算可能尝试返回无限位数时,使用它。

round_mode()

设置/获取舍入模式。

upgrade()

设置/获取升级类。当计算可能导致非整数时,操作数将升级到此类。例如,bignum 使用它。默认值为 undef,即不升级。

# with no upgrading
$x = Math::BigInt->new(12);
$y = Math::BigInt->new(5);
print $x / $y, "\n";                # 2 as a Math::BigInt

# with upgrading to Math::BigFloat
Math::BigInt -> upgrade("Math::BigFloat");
print $x / $y, "\n";                # 2.4 as a Math::BigFloat

# with upgrading to Math::BigRat (after loading Math::BigRat)
Math::BigInt -> upgrade("Math::BigRat");
print $x / $y, "\n";                # 12/5 as a Math::BigRat
downgrade()

设置/获取降级类。默认值为 undef,即不降级。Math::BigInt 不执行降级。

modify()
$x->modify('bpowd');

如果对象可以使用给定的操作进行修改,则此方法返回 0,否则返回 1。

例如,这由 Math::BigInt::Constant 使用。

config()
Math::BigInt->config("trap_nan" => 1);      # set
$accu = Math::BigInt->config("accuracy");   # get

设置或获取类变量。只读参数标记为 RO。读写参数标记为 RW。支持以下参数。

Parameter       RO/RW   Description
                        Example
============================================================
lib             RO      Name of the math backend library
                        Math::BigInt::Calc
lib_version     RO      Version of the math backend library
                        0.30
class           RO      The class of config you just called
                        Math::BigRat
version         RO      version number of the class you used
                        0.10
upgrade         RW      To which class numbers are upgraded
                        undef
downgrade       RW      To which class numbers are downgraded
                        undef
precision       RW      Global precision
                        undef
accuracy        RW      Global accuracy
                        undef
round_mode      RW      Global round mode
                        even
div_scale       RW      Fallback accuracy for division etc.
                        40
trap_nan        RW      Trap NaNs
                        undef
trap_inf        RW      Trap +inf/-inf
                        undef

构造函数方法

new()
$x = Math::BigInt->new($str,$A,$P,$R);

从标量或另一个 Math::BigInt 对象创建一个新的 Math::BigInt 对象。输入被接受为十进制、十六进制(以 '0x' 开头)、八进制(以 ('0o') 开头)或二进制(以 '0b' 开头)。

有关接受的输入格式的更多信息,请参阅 "输入"

from_dec()
$x = Math::BigInt->from_dec("314159");    # input is decimal

将输入解释为十进制。它等效于 new(),但不接受除表示有限十进制数的字符串以外的任何内容。

from_hex()
$x = Math::BigInt->from_hex("0xcafe");    # input is hexadecimal

将输入解释为十六进制字符串。可选地使用 "0x" 或 "x" 前缀。如果存在,可以在前缀后或任何两个数字之间放置单个下划线字符。如果输入无效,则返回 NaN。

from_oct()
$x = Math::BigInt->from_oct("0775");      # input is octal

将输入解释为八进制字符串并返回相应的数值。可选地使用 "0"(零)前缀。如果存在,可以在前缀后或任何两个数字之间放置单个下划线字符。如果输入无效,则返回 NaN。

from_bin()
$x = Math::BigInt->from_bin("0b10011");   # input is binary

将输入解释为二进制字符串。可选地使用 "0b" 或 "b" 前缀。如果存在,可以在前缀后或任何两个数字之间放置单个下划线字符。如果输入无效,则返回 NaN。

from_bytes()
$x = Math::BigInt->from_bytes("\xf3\x6b");  # $x = 62315

将输入解释为字节字符串,假设大端字节序。输出始终为非负有限整数。

在某些特殊情况下,from_bytes() 与 unpack() 执行的转换匹配。

$b = "\x4e";                             # one char byte string
$x = Math::BigInt->from_bytes($b);       # = 78
$y = unpack "C", $b;                     # ditto, but scalar

$b = "\xf3\x6b";                         # two char byte string
$x = Math::BigInt->from_bytes($b);       # = 62315
$y = unpack "S>", $b;                    # ditto, but scalar

$b = "\x2d\xe0\x49\xad";                 # four char byte string
$x = Math::BigInt->from_bytes($b);       # = 769673645
$y = unpack "L>", $b;                    # ditto, but scalar

$b = "\x2d\xe0\x49\xad\x2d\xe0\x49\xad"; # eight char byte string
$x = Math::BigInt->from_bytes($b);       # = 3305723134637787565
$y = unpack "Q>", $b;                    # ditto, but scalar
from_base()

给定一个字符串、一个基数和一个可选的排序序列,将字符串解释为给定基数中的数字。排序序列描述字符串中每个字符的值。

如果没有给出排序序列,则使用默认排序序列。如果基数小于或等于 36,则排序序列是包含 36 个字符 "0" 到 "9" 和 "A" 到 "Z" 的字符串。在这种情况下,输入中的字母大小写将被忽略。如果基数大于 36 且小于或等于 62,则排序序列是包含 62 个字符 "0" 到 "9"、"A" 到 "Z" 和 "a" 到 "z" 的字符串。大于 62 的基数需要显式指定排序序列。

这些示例显示了标准二进制、八进制和十六进制转换。所有情况都返回 250。

$x = Math::BigInt->from_base("11111010", 2);
$x = Math::BigInt->from_base("372", 8);
$x = Math::BigInt->from_base("fa", 16);

当基数小于或等于 36 且没有给出排序序列时,字母大小写将被忽略,因此这两个也返回 250

$x = Math::BigInt->from_base("6Y", 16);
$x = Math::BigInt->from_base("6y", 16);

当基数大于 36 且没有给出排序序列时,默认排序序列包含大写和小写字母,因此输入中的字母大小写不会被忽略

$x = Math::BigInt->from_base("6S", 37);         # $x is 250
$x = Math::BigInt->from_base("6s", 37);         # $x is 276
$x = Math::BigInt->from_base("121", 3);         # $x is 16
$x = Math::BigInt->from_base("XYZ", 36);        # $x is 44027
$x = Math::BigInt->from_base("Why", 42);        # $x is 58314

排序序列可以是任何一组唯一的字符。这两个情况是等价的

$x = Math::BigInt->from_base("100", 2, "01");   # $x is 4
$x = Math::BigInt->from_base("|--", 2, "-|");   # $x is 4
from_base_num()

返回一个新的 Math::BigInt 对象,该对象由一个值数组和一个基数给出。此方法等效于 from_base(),但作用于数组中的数字而不是字符串中的字符。与 from_base() 不同,所有输入值都可以任意大。

$x = Math::BigInt->from_base_num([1, 1, 0, 1], 2)     # $x is 13
$x = Math::BigInt->from_base_num([3, 125, 39], 128)   # $x is 65191
bzero()
$x = Math::BigInt->bzero();
$x->bzero();

返回一个表示零的新 Math::BigInt 对象。如果用作实例方法,则将该值分配给调用者。

bone()
$x = Math::BigInt->bone();          # +1
$x = Math::BigInt->bone("+");       # +1
$x = Math::BigInt->bone("-");       # -1
$x->bone();                         # +1
$x->bone("+");                      # +1
$x->bone('-');                      # -1

创建一个表示一的新 Math::BigInt 对象。可选参数为 '-' 或 '+',指示您想要加一还是减一。如果用作实例方法,则将该值分配给调用者。

binf()
$x = Math::BigInt->binf($sign);

创建一个表示无穷大的新 Math::BigInt 对象。可选参数为 '-' 或 '+',指示您想要无穷大还是负无穷大。如果用作实例方法,则将该值分配给调用者。

$x->binf();
$x->binf('-');
bnan()
$x = Math::BigInt->bnan();

创建一个表示 NaN(非数字)的新 Math::BigInt 对象。如果用作实例方法,则将该值分配给调用者。

$x->bnan();
bpi()
$x = Math::BigInt->bpi(100);        # 3
$x->bpi(100);                       # 3

创建一个表示 PI 的新 Math::BigInt 对象。如果用作实例方法,则将该值分配给调用者。对于 Math::BigInt,这始终返回 3。

如果升级生效,则返回 PI,并根据当前舍入模式舍入到 N 位数字

use Math::BigFloat;
use Math::BigInt upgrade => "Math::BigFloat";
print Math::BigInt->bpi(3), "\n";           # 3.14
print Math::BigInt->bpi(100), "\n";         # 3.1415....
copy()
$x->copy();         # make a true copy of $x (unlike $y = $x)
as_int()
as_number()

当 Math::BigInt 遇到它无法处理的对象时,就会调用这些方法。例如,假设 $x 是一个 Math::BigInt 或其子类,而 $y 已定义,但不是 Math::BigInt 或其子类。如果你这样做

$x -> badd($y);

$y 需要被转换为 $x 可以处理的对象。这是通过首先检查 $y 是否是 $x 可以升级到的东西来完成的。如果是这样,就不会进行进一步的尝试。接下来是查看 $y 是否支持方法 as_int()。如果支持,则调用 as_int(),但如果它不支持,则接下来是查看 $y 是否支持方法 as_number()。如果支持,则调用 as_number()。方法 as_int()(和 as_number())应该返回一个与 $x 类相同、其子类或 ref($x)->new() 可以解析以创建对象的字符串。

as_number()as_int() 的别名。as_number 在 v1.22 中引入,而 as_int() 在 v1.68 中引入。

在 Math::BigInt 中,as_int()copy() 的效果相同。

as_float()

将参数作为 Math::BigFloat 对象返回。

as_rat()

将参数作为 Math::BigRat 对象返回。

布尔方法

这些方法都不会修改被调用对象。

is_zero()
$x->is_zero();              # true if $x is 0

如果被调用对象为零,则返回 true,否则返回 false。

is_one( [ SIGN ])
$x->is_one();               # true if $x is +1
$x->is_one("+");            # ditto
$x->is_one("-");            # true if $x is -1

如果被调用对象为一,则返回 true,否则返回 false。

is_finite()
$x->is_finite();    # true if $x is not +inf, -inf or NaN

如果被调用对象是有限数,则返回 true,即它既不是 +inf,也不是 -inf,也不是 NaN。

is_inf( [ SIGN ] )
$x->is_inf();               # true if $x is +inf
$x->is_inf("+");            # ditto
$x->is_inf("-");            # true if $x is -inf

如果被调用对象是无穷大,则返回 true,否则返回 false。

is_nan()
$x->is_nan();               # true if $x is NaN
is_positive()
is_pos()
$x->is_positive();          # true if > 0
$x->is_pos();               # ditto

如果被调用对象为正,则返回 true,否则返回 false。NaN 既不是正数也不是负数。

is_negative()
is_neg()
$x->is_negative();          # true if < 0
$x->is_neg();               # ditto

如果被调用对象为负,则返回 true,否则返回 false。NaN 既不是正数也不是负数。

is_non_positive()
$x->is_non_positive();      # true if <= 0

如果被调用者为负数或零,则返回真。

is_non_negative()
$x->is_non_negative();      # true if >= 0

如果被调用者为正数或零,则返回真。

is_odd()
$x->is_odd();               # true if odd, false for even

如果被调用者为奇数,则返回真,否则返回假。NaN+inf-inf 既不是奇数也不是偶数。

is_even()
$x->is_even();              # true if $x is even

如果被调用者为偶数,则返回真,否则返回假。NaN+inf-inf 不是整数,既不是奇数也不是偶数。

is_int()
$x->is_int();               # true if $x is an integer

如果被调用者为整数,则返回真,否则返回假。NaN+inf-inf 不是整数。

比较方法

这些方法都不会修改被调用者对象。请注意,NaN 既不小于、大于也不等于任何其他值,即使是 NaN

bcmp()
$x->bcmp($y);

如果 $x 小于、等于或大于 $y,则分别返回 -1、0、1。如果任何操作数为 NaN,则返回 undef。

bacmp()
$x->bacmp($y);

如果 $x 的绝对值小于、等于或大于 $y 的绝对值,则分别返回 -1、0、1。如果任何操作数为 NaN,则返回 undef。

beq()
$x -> beq($y);

当且仅当 $x 等于 $y 时返回真,否则返回假。

bne()
$x -> bne($y);

当且仅当 $x 不等于 $y 时返回真,否则返回假。

blt()
$x -> blt($y);

当且仅当 $x 等于 $y 时返回真,否则返回假。

ble()
$x -> ble($y);

当且仅当 $x 小于或等于 $y 时返回真,否则返回假。

bgt()
$x -> bgt($y);

当且仅当 $x 大于 $y 时返回真,否则返回假。

bge()
$x -> bge($y);

当且仅当 $x 大于或等于 $y 时返回真,否则返回假。

算术方法

这些方法会修改被调用者对象并返回它。

bneg()
$x->bneg();

对数字取反,例如将符号从 '+' 更改为 '-',或将符号从 '+inf' 更改为 '-inf'。对 NaN 或零不做任何操作。

babs()
$x->babs();

将数字设置为其绝对值,例如将符号从 '-' 更改为 '+',并将符号从 '-inf' 更改为 '+inf'。对 NaN 或正数不做任何操作。

bsgn()
$x->bsgn();

符号函数。将数字设置为 -1、0 或 1,具体取决于数字是负数、零还是正数。不修改 NaN。

bnorm()
$x->bnorm();                        # normalize (no-op)

规范化数字。这是一个无操作,仅为了向后兼容而提供。

binc()
$x->binc();                 # increment x by 1
bdec()
$x->bdec();                 # decrement x by 1
badd()
$x->badd($y);               # addition (add $y to $x)
bsub()
$x->bsub($y);               # subtraction (subtract $y from $x)
bmul()
$x->bmul($y);               # multiplication (multiply $x by $y)
bmuladd()
$x->bmuladd($y,$z);

将 $x 乘以 $y,然后将 $z 加到结果中。

此方法是在 Math::BigInt 的 v1.87 版本(2007 年 6 月)中添加的。

bdiv()
$x->bdiv($y);               # divide, set $x to quotient

通过执行向下取整除法(F-除法)将 $x 除以 $y,其中商是两个操作数的向下取整(向负无穷大舍入)商。在列表上下文中,返回商和余数。余数要么为零,要么与第二个操作数具有相同的符号。在标量上下文中,只返回商。

商始终是小于或等于两个操作数的实值商的最大整数,而余数(当它不为零时)始终与第二个操作数具有相同的符号;因此,例如

  1 /  4  => ( 0,  1)
  1 / -4  => (-1, -3)
 -3 /  4  => (-1,  1)
 -3 / -4  => ( 0, -3)
-11 /  2  => (-5,  1)
 11 / -2  => (-5, -1)

重载运算符 % 的行为与 Perl 内置 % 运算符的行为一致(如 perlop 手册页中所述),并且等式

$x == ($x / $y) * $y + ($x % $y)

对任何有限的 $x 和有限的非零 $y 成立。

Perl 的“use integer”可能会改变 % 和 / 对标量的行为。这是因为在 'use integer' 下,Perl 会执行底层 C 库认为正确的操作,而这会因情况而异。但是,“use integer”不会改变使用 Math::BigInt 对象的方式。

btdiv()
$x->btdiv($y);              # divide, set $x to quotient

通过执行截断除法(T-除法)将 $x 除以 $y,其中商是两个操作数的截断(向零舍入)商。在列表上下文中,返回商和余数。余数要么为零,要么与第一个操作数具有相同的符号。在标量上下文中,只返回商。

bmod()
$x->bmod($y);               # modulus (x % y)

返回 $x 模 $y,即地板除法(F-除法)后的余数。此方法类似于 Perl 的 % 运算符。参见 "bdiv()"

btmod()
$x->btmod($y);              # modulus

返回截断除法(T-除法)后的余数。参见 "btdiv()"

bmodinv()
$x->bmodinv($mod);          # modular multiplicative inverse

返回 $x$mod 的乘法逆元。如果

$y = $x -> copy() -> bmodinv($mod)

$y 是最接近零的数字,并且与 $mod 的符号相同,满足

($x * $y) % $mod = 1 % $mod

如果 $x$y 不为零,则它们必须是互质的,即 bgcd($y, $mod)==1。当不存在模乘法逆元时,返回 'NaN'。

bmodpow()
$num->bmodpow($exp,$mod);           # modular exponentiation
                                    # ($num**$exp % $mod)

使用二进制指数运算返回 $num$exp 次方在模 $mod 中的值。bmodpow 远优于编写

$num ** $exp % $mod

因为它速度快得多 - 它尽可能地将内部变量简化为模,因此它对较小的数字进行操作。

bmodpow 也支持负指数。

bmodpow($num, -1, $mod)

bmodinv($num, $mod)
bpow()
$x->bpow($y);               # power of arguments (x ** y)

bpow()(以及舍入函数)现在修改第一个参数并返回它,这与旧代码不同,旧代码保留它并只返回结果。这是为了与 badd() 等保持一致。前三个修改 $x,最后一个不会

print bpow($x,$i),"\n";         # modify $x
print $x->bpow($i),"\n";        # ditto
print $x **= $i,"\n";           # the same
print $x ** $i,"\n";            # leave $x alone

但是,$x **= $y 的形式比 $x = $x ** $y; 快。

blog()
$x->blog($base, $accuracy);         # logarithm of x to the base $base

如果未定义 $base,则使用欧拉数 (e)

print $x->blog(undef, 100);         # log(x) to 100 digits
bexp()
$x->bexp($accuracy);                # calculate e ** X

计算表达式 e ** $x,其中 e 是欧拉数。

此方法是在 Math::BigInt 的 v1.82 版本(2007 年 4 月)中添加的。

另请参见 "blog()"

bnok()
$x->bnok($y);               # x over y (binomial coefficient n over k)

计算二项式系数 n 除以 k,也称为“选择”函数,即

( n )       n!
|   |  = --------
( k )    k!(n-k)!

当 n 和 k 为非负数时。此方法实现了完整的 Kronenburg 扩展(Kronenburg, M.J. "The Binomial Coefficient for Negative Arguments." 18 May 2011. http://arxiv.org/abs/1105.3689/),以下伪代码说明了这一点

if n >= 0 and k >= 0:
    return binomial(n, k)
if k >= 0:
    return (-1)^k*binomial(-n+k-1, k)
if k <= n:
    return (-1)^(n-k)*binomial(-k-1, n-k)
else
    return 0

对于负整数 n、k,其行为与 Maple 和 Mathematica 函数的行为相同。

buparrow()
uparrow()
$a -> buparrow($n, $b);         # modifies $a
$x = $a -> uparrow($n, $b);     # does not modify $a

此方法实现了 Knuth 的向上箭头符号,其中 $n 是一个非负整数,表示向上箭头的数量。$n = 0 表示乘法,$n = 1 表示指数,$n = 2 表示四次方,$n = 3 表示六次方等。以下说明了 $n 的前几个值的之间的关系。

参见 https://en.wikipedia.org/wiki/Knuth%27s_up-arrow_notation

backermann()
ackermann()
$m -> backermann($n);           # modifies $a
$x = $m -> ackermann($n);       # does not modify $a

此方法实现阿克曼函数

          / n + 1              if m = 0
A(m, n) = | A(m-1, 1)          if m > 0 and n = 0
          \ A(m-1, A(m, n-1))  if m > 0 and n > 0

即使对于较小的输入,它的值也会迅速增长。例如,A(4, 2) 是一个 19729 位十进制整数。

参见 https://en.wikipedia.org/wiki/Ackermann_function

bsin()
my $x = Math::BigInt->new(1);
print $x->bsin(100), "\n";

计算 $x 的正弦值,并修改 $x 的值。

在 Math::BigInt 中,除非升级生效,否则结果将截断为整数。

此方法是在 Math::BigInt 的 v1.87 版本(2007 年 6 月)中添加的。

bcos()
my $x = Math::BigInt->new(1);
print $x->bcos(100), "\n";

计算 $x 的余弦值,并修改 $x 的值。

在 Math::BigInt 中,除非升级生效,否则结果将截断为整数。

此方法是在 Math::BigInt 的 v1.87 版本(2007 年 6 月)中添加的。

batan()
my $x = Math::BigFloat->new(0.5);
print $x->batan(100), "\n";

计算 $x 的反正切值,并修改 $x 的值。

在 Math::BigInt 中,除非升级生效,否则结果将截断为整数。

此方法是在 Math::BigInt 的 v1.87 版本(2007 年 6 月)中添加的。

batan2()
my $x = Math::BigInt->new(1);
my $y = Math::BigInt->new(1);
print $y->batan2($x), "\n";

计算 $y 除以 $x 的反正切值,并修改 $y 的值。

在 Math::BigInt 中,除非升级生效,否则结果将截断为整数。

此方法是在 Math::BigInt 的 v1.87 版本(2007 年 6 月)中添加的。

bsqrt()
$x->bsqrt();                # calculate square root

bsqrt() 返回截断为整数的平方根。

如果您想要更精确的平方根近似值,请使用

$x = Math::BigFloat->new(12);
Math::BigFloat->precision(0);
Math::BigFloat->round_mode('even');
print $x->copy->bsqrt(),"\n";           # 4

Math::BigFloat->precision(2);
print $x->bsqrt(),"\n";                 # 3.46
print $x->bsqrt(3),"\n";                # 3.464
broot()
$x->broot($N);

计算 $x 的 N 次方根。

bfac()
$x->bfac();             # factorial of $x

返回 $x 的阶乘,即 $x*($x-1)*($x-2)*...*2*1,所有正整数到 $x(包括 $x)的乘积。$x 必须大于 -1。N 的阶乘通常写成 N!,或 N!1,当使用多重阶乘表示法时。

bdfac()
$x->bdfac();                # double factorial of $x

返回 $x 的双阶乘,即 $x*($x-2)*($x-4)*... $x 必须大于 -2。N 的双阶乘通常写成 N!!,或 N!2,当使用多重阶乘表示法时。

btfac()
$x->btfac();            # triple factorial of $x

返回 $x 的三阶乘,即 $x*($x-3)*($x-6)*... $x 必须大于 -3。N 的三阶乘通常写成 N!!!,或 N!3,当使用多重阶乘表示法时。

bmfac()
$x->bmfac($k);          # $k'th multifactorial of $x

返回 $x 的多重阶乘,即 $x*($x-$k)*($x-2*$k)*... $x 必须大于 -$k。N 的多重阶乘通常写成 N!K。

bfib()
$F = $n->bfib();            # a single Fibonacci number
@F = $n->bfib();            # a list of Fibonacci numbers

在标量上下文中,返回单个斐波那契数。在列表上下文中,返回斐波那契数列表。被调用者是输出中的最后一个元素。

斐波那契数列定义为

F(0) = 0
F(1) = 1
F(n) = F(n-1) + F(n-2)

在列表上下文中,F(0) 和 F(n) 分别是输出中的第一个和最后一个数字。例如,如果 $n 为 12,则 @F = $n->bfib() 返回以下值,从 F(0) 到 F(12)

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144

该序列也可以使用重新排列的递归关系扩展到负索引 n

F(n-2) = F(n) - F(n-1)

给出双向序列

   n  -7  -6  -5  -4  -3  -2  -1   0   1   2   3   4   5   6   7
F(n)  13  -8   5  -3   2  -1   1   0   1   1   2   3   5   8  13

如果 $n 为 -12,则返回以下值,从 F(0) 到 F(12)

0, 1, -1, 2, -3, 5, -8, 13, -21, 34, -55, 89, -144
blucas()
$F = $n->blucas();          # a single Lucas number
@F = $n->blucas();          # a list of Lucas numbers

在标量上下文中,返回单个卢卡斯数。在列表上下文中,返回卢卡斯数列表。被调用者是输出中的最后一个元素。

卢卡斯序列定义为

L(0) = 2
L(1) = 1
L(n) = L(n-1) + L(n-2)

在列表上下文中,L(0) 和 L(n) 分别是输出中的第一个和最后一个数字。例如,如果 $n 为 12,则 @L = $n->blucas() 返回以下值,从 L(0) 到 L(12)

2, 1, 3, 4, 7, 11, 18, 29, 47, 76, 123, 199, 322

该序列也可以使用重新排列的递归关系扩展到负索引 n

L(n-2) = L(n) - L(n-1)

给出双向序列

   n  -7  -6  -5  -4  -3  -2  -1   0   1   2   3   4   5   6   7
L(n)  29 -18  11  -7   4  -3   1   2   1   3   4   7  11  18  29

如果 $n 为 -12,则返回以下值,从 L(0) 到 L(-12)

2, 1, -3, 4, -7, 11, -18, 29, -47, 76, -123, 199, -322
brsft()
$x->brsft($n);              # right shift $n places in base 2
$x->brsft($n, $b);          # right shift $n places in base $b

后者等效于

$x -> bdiv($b -> copy() -> bpow($n))
blsft()
$x->blsft($n);              # left shift $n places in base 2
$x->blsft($n, $b);          # left shift $n places in base $b

后者等效于

$x -> bmul($b -> copy() -> bpow($n))

位运算方法

band()
$x->band($y);               # bitwise and
bior()
$x->bior($y);               # bitwise inclusive or
bxor()
$x->bxor($y);               # bitwise exclusive or
bnot()
$x->bnot();                 # bitwise not (two's complement)

二进制补码(按位取反)。这等效于,但比以下方法更快

$x->binc()->bneg();

舍入方法

round()
$x->round($A,$P,$round_mode);

使用舍入模式 $round_mode 将 $x 舍入到精度 $A 或小数位数 $P

bround()
$x->bround($N);               # accuracy: preserve $N digits

将 $x 舍入到 $N 位精度。

bfround()
$x->bfround($N);

舍入到 10**$N 的倍数。示例

Input            N          Result

123456.123456    3          123500
123456.123456    2          123450
123456.123456   -2          123456.12
123456.123456   -3          123456.123
bfloor()
$x->bfloor();

将 $x 舍入到负无穷大,即,将 $x 设置为小于或等于 $x 的最大整数。

bceil()
$x->bceil();

将 $x 舍入到正无穷大,即,将 $x 设置为大于或等于 $x 的最小整数)。

bint()
$x->bint();

将 $x 舍入到零。

其他数学方法

bgcd()
$x -> bgcd($y);             # GCD of $x and $y
$x -> bgcd($y, $z, ...);    # GCD of $x, $y, $z, ...

返回最大公约数 (GCD)。

blcm()
$x -> blcm($y);             # LCM of $x and $y
$x -> blcm($y, $z, ...);    # LCM of $x, $y, $z, ...

返回最小公倍数 (LCM)。

对象属性方法

sign()
$x->sign();

返回 $x 的符号,即 +--inf+inf 或 NaN。

如果您希望 $x 具有特定符号,请使用以下方法之一

$x->babs();                 # '+'
$x->babs()->bneg();         # '-'
$x->bnan();                 # 'NaN'
$x->binf();                 # '+inf'
$x->binf('-');              # '-inf'
digit()
$x->digit($n);       # return the nth digit, counting from right

如果 $n 为负数,则返回从左侧开始计数的数字。

digitsum()
$x->digitsum();

计算 10 进制数字的总和并返回结果。

bdigitsum()
$x->bdigitsum();

计算 10 进制数字的总和并将结果分配给调用者。

length()
$x->length();
($xl, $fl) = $x->length();

返回数字十进制表示中的数字数量。在列表上下文中,返回整数和小数部分的长度。对于 Math::BigInt 对象,小数部分的长度始终为 0。

以下可能不会按预期执行

$c = Math::BigInt->new(123);
print $c->length(),"\n";                # prints 30

它会打印数字和小数部分中的数字数量,因为 print 在列表上下文中调用 length()。使用类似以下内容

print scalar $c->length(),"\n";         # prints 3
mantissa()
$x->mantissa();

将 $x 的带符号尾数作为 Math::BigInt 返回。

exponent()
$x->exponent();

将 $x 的指数作为 Math::BigInt 返回。

parts()
$x->parts();

返回有效数字(尾数)和指数作为整数。在 Math::BigFloat 中,两者都作为 Math::BigInt 对象返回。

sparts()

返回有效数字(尾数)和指数作为整数。在标量上下文中,只返回有效数字。有效数字是最小绝对值的整数。sparts() 的输出对应于 bsstr() 的输出。

在 Math::BigInt 中,此方法与 parts() 相同。

nparts()

返回对应于规范化表示的有效数字(尾数)和指数。在标量上下文中,只返回有效数字。对于有限非零数,有效数字的绝对值大于或等于 1 且小于 10。nparts() 的输出对应于 bnstr() 的输出。在 Math::BigInt 中,如果有效数字不能表示为整数,则执行升级或返回 NaN。

eparts()

返回与工程记数法相对应的有效数字(尾数)和指数。在标量上下文中,只返回有效数字。对于有限的非零数字,有效数字的绝对值大于或等于 1 且小于 1000,指数是 3 的倍数。eparts() 的输出对应于 bestr() 的输出。在 Math::BigInt 中,如果有效数字不能表示为整数,则执行升级或返回 NaN。

dparts()

返回整数部分和小数部分。如果小数部分不能表示为整数,则执行升级或返回 NaN。dparts() 的输出对应于 bdstr() 的输出。

fparts()

返回最小的分子和分母,使得分子除以分母得到原始值。对于有限数,这两个值都是整数。助记符:分数。

numerator()

"denominator()" 一起,返回最小的整数,使得分子除以分母得到原始值。在 Math::BigInt 中,numerator() 只是返回调用者的副本。

denominator()

"numerator()" 一起,返回最小的整数,使得分子除以分母得到原始值。在 Math::BigInt 中,denominator() 始终返回 1 或 NaN。

字符串转换方法

bstr()

返回使用十进制表示法表示数字的字符串。在 Math::BigFloat 中,输出根据当前精度或精度进行零填充(如果有定义)。

bsstr()

返回使用科学记数法表示数字的字符串,其中有效数字(尾数)和指数都是整数。输出对应于 sparts() 的输出。

  123 is returned as "123e+0"
 1230 is returned as "123e+1"
12300 is returned as "123e+2"
12000 is returned as "12e+3"
10000 is returned as "1e+4"
bnstr()

返回使用规范化记数法表示数字的字符串,这是科学记数法的最常见变体。对于有限的非零数字,有效数字的绝对值大于或等于 1 且小于 10。输出对应于 nparts() 的输出。

  123 is returned as "1.23e+2"
 1230 is returned as "1.23e+3"
12300 is returned as "1.23e+4"
12000 is returned as "1.2e+4"
10000 is returned as "1e+4"
bestr()

返回使用工程记数法表示数字的字符串。对于有限的非零数字,有效数字的绝对值大于或等于 1 且小于 1000,指数是 3 的倍数。输出对应于 eparts() 的输出。

  123 is returned as "123e+0"
 1230 is returned as "1.23e+3"
12300 is returned as "12.3e+3"
12000 is returned as "12e+3"
10000 is returned as "10e+3"
bdstr()

返回使用十进制表示法表示数字的字符串。输出对应于 dparts() 的输出。

  123 is returned as "123"
 1230 is returned as "1230"
12300 is returned as "12300"
12000 is returned as "12000"
10000 is returned as "10000"
bfstr()

返回使用分数表示法表示数字的字符串。输出对应于 fparts() 的输出。

    12.345 is returned as "2469/200"
   123.45 is returned as "2469/20"
  1234.5 is returned as "2469/2"
 12345 is returned as "12345"
123450 is returned as "123450"
to_hex()
$x->to_hex();

返回数字的十六进制字符串表示形式。另请参见 from_hex()。

to_bin()
$x->to_bin();

返回数字的二进制字符串表示形式。另请参见 from_bin()。

to_oct()
$x->to_oct();

返回数字的八进制字符串表示形式。另请参见 from_oct()。

to_bytes()
$x = Math::BigInt->new("1667327589");
$s = $x->to_bytes();                    # $s = "cafe"

使用大端字节序返回数字的字节字符串表示形式。被调用者必须是非负的有限整数。另请参见 from_bytes()。

to_base()
$x = Math::BigInt->new("250");
$x->to_base(2);     # returns "11111010"
$x->to_base(8);     # returns "372"
$x->to_base(16);    # returns "fa"

返回给定基数中数字的字符串表示形式。如果给出排序序列,则排序序列决定输出中使用哪些字符。

以下是一些更多示例

$x = Math::BigInt->new("16")->to_base(3);       # returns "121"
$x = Math::BigInt->new("44027")->to_base(36);   # returns "XYZ"
$x = Math::BigInt->new("58314")->to_base(42);   # returns "Why"
$x = Math::BigInt->new("4")->to_base(2, "-|");  # returns "|--"

有关信息和示例,请参见 from_base()。

to_base_num()

将给定数字转换为给定基数。此方法等效于 _to_base(),但返回数组中的数字而不是字符串中的字符。在输出中,第一个元素是最重要的。与 _to_base() 不同,所有输入值都可以任意大。

$x = Math::BigInt->new(13);
$x->to_base_num(2);                         # returns [1, 1, 0, 1]

$x = Math::BigInt->new(65191);
$x->to_base_num(128);                       # returns [3, 125, 39]
as_hex()
$x->as_hex();

to_hex() 相同,但带有 "0x" 前缀。

as_bin()
$x->as_bin();

to_bin() 相同,但带有 "0b" 前缀。

as_oct()
$x->as_oct();

to_oct() 相同,但带有 "0" 前缀。

as_bytes()

这只是 to_bytes() 的别名。

其他转换方法

numify()
print $x->numify();

从 $x 返回一个 Perl 标量。每当需要标量时,它都会自动使用,例如在数组索引操作中。

实用程序方法

这些实用程序方法已公开

dec_str_to_dec_flt_str()

接受一个表示任何使用十进制表示法的有效数字的字符串,并将其转换为一个表示使用十进制浮点表示法的相同数字的字符串。输出由五个部分组成:有效数字的符号、有效数字的绝对值作为最小的可能整数、字母 "e"、指数的符号以及指数的绝对值。如果输入无效,则不返回任何内容。

$str2 = $class -> dec_str_to_dec_flt_str($str1);

一些示例

Input           Output
31400.00e-4     +314e-2
-0.00012300e8   -123e+2
0               +0e+0
hex_str_to_dec_flt_str()

接受使用十六进制表示法表示任何有效数字的字符串,并将其转换为使用十进制浮点表示法表示相同数字的字符串。输出格式与 "dec_str_to_dec_flt_str()" 相同。

$str2 = $class -> hex_str_to_dec_flt_str($str1);

一些示例

Input           Output
0xff            +255e+0

一些示例

oct_str_to_dec_flt_str()

接受使用八进制表示法表示任何有效数字的字符串,并将其转换为使用十进制浮点表示法表示相同数字的字符串。输出格式与 "dec_str_to_dec_flt_str()" 相同。

$str2 = $class -> oct_str_to_dec_flt_str($str1);
bin_str_to_dec_flt_str()

接受使用二进制表示法表示任何有效数字的字符串,并将其转换为使用十进制浮点表示法表示相同数字的字符串。输出格式与 "dec_str_to_dec_flt_str()" 相同。

$str2 = $class -> bin_str_to_dec_flt_str($str1);
dec_str_to_dec_str()

接受使用十进制表示法表示任何有效数字的字符串,并将其转换为使用十进制表示法表示相同数字的字符串。如果数字表示整数,则输出包含符号和绝对值。如果数字表示非整数,则输出包含符号、数字的整数部分、小数点“.”和数字的小数部分,不包含任何尾随零。如果输入无效,则不返回任何内容。

hex_str_to_dec_str()

接受使用十六进制表示法表示任何有效数字的字符串,并将其转换为使用十进制表示法表示相同数字的字符串。输出格式与 "dec_str_to_dec_str()" 相同。

oct_str_to_dec_str()

接受使用八进制表示法表示任何有效数字的字符串,并将其转换为使用十进制表示法表示相同数字的字符串。输出格式与 "dec_str_to_dec_str()" 相同。

bin_str_to_dec_str()

接受使用二进制表示法表示任何有效数字的字符串,并将其转换为使用十进制表示法表示相同数字的字符串。输出格式与 "dec_str_to_dec_str()" 相同。

准确性和精度

Math::BigInt 和 Math::BigFloat 完全支持基于精度和有效数字的舍入,包括在每次运算后自动舍入,以及手动舍入。

本节描述了 Math::BigInt 和 Math::BigFloat 中的精度/有效数字处理方式,包括过去和现在的处理方式,以及所有术语和缩写的解释。

尚未实现的功能(但有正确的描述)用 '!' 标记,需要解答的问题用 '?' 标记。

下一段将简要介绍本文中使用的术语(因为这些术语可能与其他人或文档中使用的术语不同)。

在本文的其余部分,将使用 A(表示有效数字)、P(表示精度)、F(表示回退)和 R(表示舍入模式)作为缩写。

精度 P

精度是指小数点前(正数)或小数点后(负数)的固定位数。例如,123.45 的精度为 -2。0 表示整数,例如 123(或 120)。精度为 2 表示小数点左侧至少两位数字为零,因此 123 且 P = 1 变为 120。请注意,小数点前有零的数字可能具有不同的精度,因为 1200 可以有 P = 0、1 或 2(取决于初始值)。当小数点后的数字为零时,它也可以有 p < 0。

字符串输出(浮点数)用零填充。

Initial value    P      A       Result          String
------------------------------------------------------------
1234.01         -3              1000            1000
1234            -2              1200            1200
1234.5          -1              1230            1230
1234.001         1              1234            1234.0
1234.01          0              1234            1234
1234.01          2              1234.01         1234.01
1234.01          5              1234.01         1234.01000

对于 Math::BigInt 对象,不会进行填充。

有效数字 A

有效数字是指有效数字的位数。前导零不计入。当数字中包含零或尾随零时,数字的有效数字可能大于非零数字的位数。例如,123.456 的 A 为 6,10203 的 A 为 5,123.0506 的 A 为 7,123.45000 的 A 为 8,0.000123 的 A 为 3。

字符串输出(浮点数)用零填充。

Initial value    P      A       Result          String
------------------------------------------------------------
1234.01                 3       1230            1230
1234.01                 6       1234.01         1234.01
1234.1                  8       1234.1          1234.1000

对于 Math::BigInt 对象,不会进行填充。

回退 F

当 A 和 P 都未定义时,这将用作除法运算时的回退有效数字。

舍入模式 R

对数字进行舍入时,可以采用不同的“样式”或“类型”的舍入。(请注意,Math::Round 中的随机舍入尚未实现。)

定向舍入

这些舍入模式总是朝同一个方向舍入。

'trunc'

向零舍入。删除所有舍入位数后的数字,即用零替换它们。因此,987.65 舍入到十位(P=1)变为 980,舍入到第四位有效数字变为 987.6(A=4)。123.456 舍入到小数点后第二位(P=-2)变为 123.46。这对应于 IEEE 754 舍入模式 'roundTowardZero'。

四舍五入

这些舍入模式舍入到最接近的数字。它们在如何确定在出现平局的模棱两可情况下舍入的方向上有所不同。

'even'

舍入到最接近的偶数数字,例如,当舍入到最接近的整数时,-5.5 变为 -6,4.5 变为 4,但 4.501 变为 5。这对应于 IEEE 754 舍入模式 'roundTiesToEven'。

'odd'

舍入到最接近的奇数数字,例如,当舍入到最接近的整数时,4.5 变为 5,-5.5 变为 -5,但 5.501 变为 6。这对应于 IEEE 754 舍入模式 'roundTiesToOdd'。

'+inf'

向正无穷大舍入,即始终向上舍入。例如,当舍入到最接近的整数时,4.5 变为 5,-5.5 变为 -5,而 4.501 也变为 5。这对应于 IEEE 754 舍入模式 'roundTiesToPositive'。

'-inf'

向负无穷大舍入,即始终向下舍入。例如,当舍入到最接近的整数时,4.5 变为 4,-5.5 变为 -6,但 4.501 变为 5。这对应于 IEEE 754 舍入模式 'roundTiesToNegative'。

'zero'

向零舍入,即正数向下舍入,负数向上舍入。例如,当舍入到最接近的整数时,4.5 变为 4,-5.5 变为 -5,但 4.501 变为 5。这对应于 IEEE 754 舍入模式 'roundTiesToZero'。

'common'

远离零舍入,即舍入到绝对值最大的数字。例如,当舍入到最接近的整数时,-1.5 变为 -2,1.5 变为 2,而 1.49 变为 1。这对应于 IEEE 754 舍入模式 'roundTiesToAway'。

在 MBI/MBF 中处理 A & P 的方式(Perl 版本 <= 5.7.2 附带的旧核心代码)如下

精度
* bfround($p) is able to round to $p number of digits after the decimal
  point
* otherwise P is unused
准确度(有效数字)
 * bround($a) rounds to $a significant digits
 * only bdiv() and bsqrt() take A as (optional) parameter
   + other operations simply create the same number (bneg etc), or
     more (bmul) of digits
   + rounding/truncating is only done when explicitly calling one
     of bround or bfround, and never for Math::BigInt (not implemented)
 * bsqrt() simply hands its accuracy argument over to bdiv.
 * the documentation and the comment in the code indicate two
   different ways on how bdiv() determines the maximum number
   of digits it should calculate, and the actual code does yet
   another thing
   POD:
     max($Math::BigFloat::div_scale,length(dividend)+length(divisor))
   Comment:
     result has at most max(scale, length(dividend), length(divisor)) digits
   Actual code:
     scale = max(scale, length(dividend)-1,length(divisor)-1);
     scale += length(divisor) - length(dividend);
   So for lx = 3, ly = 9, scale = 10, scale will actually be 16 (10
   So for lx = 3, ly = 9, scale = 10, scale will actually be 16
   (10+9-3). Actually, the 'difference' added to the scale is cal-
   culated from the number of "significant digits" in dividend and
   divisor, which is derived by looking at the length of the man-
   tissa. Which is wrong, since it includes the + sign (oops) and
   actually gets 2 for '+100' and 4 for '+101'. Oops again. Thus
   124/3 with div_scale=1 will get you '41.3' based on the strange
   assumption that 124 has 3 significant digits, while 120/7 will
   get you '17', not '17.1' since 120 is thought to have 2 signif-
   icant digits. The rounding after the division then uses the
   remainder and $y to determine whether it must round up or down.
?  I have no idea which is the right way. That's why I used a slightly more
?  simple scheme and tweaked the few failing testcases to match it.

现在它的工作原理是这样的

设置/访问
* You can set the A global via Math::BigInt->accuracy() or
  Math::BigFloat->accuracy() or whatever class you are using.
* You can also set P globally by using Math::SomeClass->precision()
  likewise.
* Globals are classwide, and not inherited by subclasses.
* to undefine A, use Math::SomeClass->accuracy(undef);
* to undefine P, use Math::SomeClass->precision(undef);
* Setting Math::SomeClass->accuracy() clears automatically
  Math::SomeClass->precision(), and vice versa.
* To be valid, A must be > 0, P can have any value.
* If P is negative, this means round to the P'th place to the right of the
  decimal point; positive values mean to the left of the decimal point.
  P of 0 means round to integer.
* to find out the current global A, use Math::SomeClass->accuracy()
* to find out the current global P, use Math::SomeClass->precision()
* use $x->accuracy() respective $x->precision() for the local
  setting of $x.
* Please note that $x->accuracy() respective $x->precision()
  return eventually defined global A or P, when $x's A or P is not
  set.
创建数字
* When you create a number, you can give the desired A or P via:
  $x = Math::BigInt->new($number,$A,$P);
* Only one of A or P can be defined, otherwise the result is NaN
* If no A or P is give ($x = Math::BigInt->new($number) form), then the
  globals (if set) will be used. Thus changing the global defaults later on
  will not change the A or P of previously created numbers (i.e., A and P of
  $x will be what was in effect when $x was created)
* If given undef for A and P, NO rounding will occur, and the globals will
  NOT be used. This is used by subclasses to create numbers without
  suffering rounding in the parent. Thus a subclass is able to have its own
  globals enforced upon creation of a number by using
  $x = Math::BigInt->new($number,undef,undef):

      use Math::BigInt::SomeSubclass;
      use Math::BigInt;

      Math::BigInt->accuracy(2);
      Math::BigInt::SomeSubclass->accuracy(3);
      $x = Math::BigInt::SomeSubclass->new(1234);

  $x is now 1230, and not 1200. A subclass might choose to implement
  this otherwise, e.g. falling back to the parent's A and P.
用法
* If A or P are enabled/defined, they are used to round the result of each
  operation according to the rules below
* Negative P is ignored in Math::BigInt, since Math::BigInt objects never
  have digits after the decimal point
* Math::BigFloat uses Math::BigInt internally, but setting A or P inside
  Math::BigInt as globals does not tamper with the parts of a Math::BigFloat.
  A flag is used to mark all Math::BigFloat numbers as 'never round'.
优先级
 * It only makes sense that a number has only one of A or P at a time.
   If you set either A or P on one object, or globally, the other one will
   be automatically cleared.
 * If two objects are involved in an operation, and one of them has A in
   effect, and the other P, this results in an error (NaN).
 * A takes precedence over P (Hint: A comes before P).
   If neither of them is defined, nothing is used, i.e. the result will have
   as many digits as it can (with an exception for bdiv/bsqrt) and will not
   be rounded.
 * There is another setting for bdiv() (and thus for bsqrt()). If neither of
   A or P is defined, bdiv() will use a fallback (F) of $div_scale digits.
   If either the dividend's or the divisor's mantissa has more digits than
   the value of F, the higher value will be used instead of F.
   This is to limit the digits (A) of the result (just consider what would
   happen with unlimited A and P in the case of 1/3 :-)
 * bdiv will calculate (at least) 4 more digits than required (determined by
   A, P or F), and, if F is not used, round the result
   (this will still fail in the case of a result like 0.12345000000001 with A
   or P of 5, but this can not be helped - or can it?)
 * Thus you can have the math done by on Math::Big* class in two modi:
   + never round (this is the default):
     This is done by setting A and P to undef. No math operation
     will round the result, with bdiv() and bsqrt() as exceptions to guard
     against overflows. You must explicitly call bround(), bfround() or
     round() (the latter with parameters).
     Note: Once you have rounded a number, the settings will 'stick' on it
     and 'infect' all other numbers engaged in math operations with it, since
     local settings have the highest precedence. So, to get SaferRound[tm],
     use a copy() before rounding like this:

       $x = Math::BigFloat->new(12.34);
       $y = Math::BigFloat->new(98.76);
       $z = $x * $y;                           # 1218.6984
       print $x->copy()->bround(3);            # 12.3 (but A is now 3!)
       $z = $x * $y;                           # still 1218.6984, without
                                               # copy would have been 1210!

   + round after each op:
     After each single operation (except for testing like is_zero()), the
     method round() is called and the result is rounded appropriately. By
     setting proper values for A and P, you can have all-the-same-A or
     all-the-same-P modes. For example, Math::Currency might set A to undef,
     and P to -2, globally.

?Maybe an extra option that forbids local A & P settings would be in order,
?so that intermediate rounding does not 'poison' further math?
覆盖全局变量
* you will be able to give A, P and R as an argument to all the calculation
  routines; the second parameter is A, the third one is P, and the fourth is
  R (shift right by one for binary operations like badd). P is used only if
  the first parameter (A) is undefined. These three parameters override the
  globals in the order detailed as follows, i.e. the first defined value
  wins:
  (local: per object, global: global default, parameter: argument to sub)
    + parameter A
    + parameter P
    + local A (if defined on both of the operands: smaller one is taken)
    + local P (if defined on both of the operands: bigger one is taken)
    + global A
    + global P
    + global F
* bsqrt() will hand its arguments to bdiv(), as it used to, only now for two
  arguments (A and P) instead of one
本地设置
* You can set A or P locally by using $x->accuracy() or
  $x->precision()
  and thus force different A and P for different objects/numbers.
* Setting A or P this way immediately rounds $x to the new value.
* $x->accuracy() clears $x->precision(), and vice versa.
舍入
* the rounding routines will use the respective global or local settings.
  bround() is for accuracy rounding, while bfround() is for precision
* the two rounding functions take as the second parameter one of the
  following rounding modes (R):
  'even', 'odd', '+inf', '-inf', 'zero', 'trunc', 'common'
* you can set/get the global R by using Math::SomeClass->round_mode()
  or by setting $Math::SomeClass::round_mode
* after each operation, $result->round() is called, and the result may
  eventually be rounded (that is, if A or P were set either locally,
  globally or as parameter to the operation)
* to manually round a number, call $x->round($A,$P,$round_mode);
  this will round the number by using the appropriate rounding function
  and then normalize it.
* rounding modifies the local settings of the number:

      $x = Math::BigFloat->new(123.456);
      $x->accuracy(5);
      $x->bround(4);

  Here 4 takes precedence over 5, so 123.5 is the result and $x->accuracy()
  will be 4 from now on.
默认值
* R: 'even'
* F: 40
* A: undef
* P: undef
备注
* The defaults are set up so that the new code gives the same results as
  the old code (except in a few cases on bdiv):
  + Both A and P are undefined and thus will not be used for rounding
    after each operation.
  + round() is thus a no-op, unless given extra parameters A and P

无穷大和非数字

虽然 Math::BigInt 对 inf 和 NaN 进行了广泛的处理,但仍然存在一些怪癖。

oct()/hex()

这些 Perl 例程目前(截至 Perl v.5.8.6)无法处理传递的 inf。

te@linux:~> perl -wle 'print 2 ** 3333'
Inf
te@linux:~> perl -wle 'print 2 ** 3333 == 2 ** 3333'
1
te@linux:~> perl -wle 'print oct(2 ** 3333)'
0
te@linux:~> perl -wle 'print hex(2 ** 3333)'
Illegal hexadecimal digit 'I' ignored at -e line 1.
0

如果您向它们传递 Math::BigInt->binf() 对象,也会出现相同的问题。由于无法重载这些例程,因此无法从 Math::BigInt 中修复此问题。

内部

您不应该关心或依赖内部表示;它可能会在未经通知的情况下更改。请使用$x->sign(); 这样的方法调用,而不是依赖内部表示。

数学库

数学计算由后端库执行。不需要指定要使用的后端库,但某些后端库比默认库快得多。

默认库

默认库是 Math::BigInt::Calc,它是在纯 Perl 中实现的,因此不需要编译器。

指定库

简单情况

use Math::BigInt;

等效于说

use Math::BigInt try => 'Calc';

您可以使用不同的后端库,例如:

use Math::BigInt try => 'GMP';

它尝试加载 Math::BigInt::GMP 库,如果指定的库无法加载,则回退到默认库。

可以通过逗号分隔多个库,例如:

use Math::BigInt try => 'GMP,Pari';

如果您需要一组特定的库,并且不允许回退到默认库,请使用“only”指定它们。

use Math::BigInt only => 'GMP,Pari';

如果您偏好一组特定的库,但希望在使用回退库时看到警告,请使用“lib”指定它们。

use Math::BigInt lib => 'GMP,Pari';

以下首先尝试查找 Math::BigInt::Foo,然后是 Math::BigInt::Bar,如果这也失败,则回退到 Math::BigInt::Calc

use Math::BigInt try => 'Foo,Math::BigInt::Bar';

使用哪个库?

注意:通用软件包不应该明确说明要使用的库;让脚本作者决定哪个最好。

Math::BigInt::GMPMath::BigInt::PariMath::BigInt::GMPz 在涉及大数字的情况下比 Math::BigInt::Calc 快得多。但是,这些库在处理非常小的数字(小于约 20 位)以及将非常大的数字转换为十进制(例如用于打印、舍入、计算它们在十进制中的长度等)时速度较慢。

因此,请仔细选择要使用的库。

不同的底层库使用不同的格式来存储数字,因此混合它们将不起作用。您不应该依赖数字具有特定的内部格式。

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

加载多个库

成功加载的第一个库将是将要使用的库。任何进一步尝试加载不同的模块都将被忽略。这是为了避免模块 A 需要数学库 X,而模块 B 需要数学库 Y,导致模块 A 和 B 不兼容的情况。例如,

use Math::BigInt;                   # loads default "Calc"
use Math::BigFloat only => "GMP";   # ignores "GMP"

符号

符号可以是 '+', '-', 'NaN', '+inf' 或 '-inf'。

'NaN' 符号用于表示输入参数不是数字或 0/0 的结果。'+inf' 和 '-inf' 分别表示正无穷大和负无穷大。当您将正数除以 0 时,您将得到 '+inf',当您将任何负数除以 0 时,您将得到 '-inf'。

示例

use Math::BigInt;

sub bigint { Math::BigInt->new(shift); }

$x = Math::BigInt->bstr("1234")       # string "1234"
$x = "$x";                            # same as bstr()
$x = Math::BigInt->bneg("1234");      # Math::BigInt "-1234"
$x = Math::BigInt->babs("-12345");    # Math::BigInt "12345"
$x = Math::BigInt->bnorm("-0.00");    # Math::BigInt "0"
$x = bigint(1) + bigint(2);           # Math::BigInt "3"
$x = bigint(1) + "2";                 # ditto ("2" becomes a Math::BigInt)
$x = bigint(1);                       # Math::BigInt "1"
$x = $x + 5 / 2;                      # Math::BigInt "3"
$x = $x ** 3;                         # Math::BigInt "27"
$x *= 2;                              # Math::BigInt "54"
$x = Math::BigInt->new(0);            # Math::BigInt "0"
$x--;                                 # Math::BigInt "-1"
$x = Math::BigInt->badd(4,5)          # Math::BigInt "9"
print $x->bsstr();                    # 9e+0

舍入示例

use Math::BigFloat;
use Test::More;

$x = Math::BigFloat->new(123.4567);
$y = Math::BigFloat->new(123.456789);
Math::BigFloat->accuracy(4);          # no more A than 4

is ($x->copy()->bround(),123.4);      # even rounding
print $x->copy()->bround(),"\n";      # 123.4
Math::BigFloat->round_mode('odd');    # round to odd
print $x->copy()->bround(),"\n";      # 123.5
Math::BigFloat->accuracy(5);          # no more A than 5
Math::BigFloat->round_mode('odd');    # round to odd
print $x->copy()->bround(),"\n";      # 123.46
$y = $x->copy()->bround(4),"\n";      # A = 4: 123.4
print "$y, ",$y->accuracy(),"\n";     # 123.4, 4

Math::BigFloat->accuracy(undef);      # A not important now
Math::BigFloat->precision(2);         # P important
print $x->copy()->bnorm(),"\n";       # 123.46
print $x->copy()->bround(),"\n";      # 123.46

转换示例

my $x = Math::BigInt->new('0b1'.'01' x 123);
print "bin: ",$x->as_bin()," hex:",$x->as_hex()," dec: ",$x,"\n";

数值文字

use Math::BigInt ':constant' 之后,给定范围内的所有数值文字都将转换为 Math::BigInt 对象。此转换在编译时发生。每个非整数都将转换为 NaN。

例如,

perl -MMath::BigInt=:constant -le 'print 2**150'

打印2**150的精确值。请注意,如果没有将常量转换为对象,表达式2**150将使用 Perl 标量计算,这会导致结果不准确。

请注意,字符串不受影响,因此

use Math::BigInt qw/:constant/;

$x = "1234567890123456789012345678901234567890"
        + "123456789123456789";

确实会给你你期望的结果。你需要在至少一个操作数周围显式地使用 Math::BigInt->new()。你还应该用引号括起较大的常量,以防止精度损失。

use Math::BigInt;

$x = Math::BigInt->new("1234567889123456789123456789123456789");

如果没有引号,Perl 首先在编译时将大数转换为浮点常量,然后在运行时将结果转换为 Math::BigInt 对象,这会导致结果不准确。

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

Perl(以及此模块)接受十六进制、八进制和二进制浮点字面量,但在 Perl 版本低于 v5.32.0 时谨慎使用它们,因为某些版本的 Perl 会静默地给出错误的结果。以下是一些以不同方式编写十进制数 314 的示例。

十六进制浮点字面量

0x1.3ap+8         0X1.3AP+8
0x1.3ap8          0X1.3AP8
0x13a0p-4         0X13A0P-4

八进制浮点字面量(带“0”前缀)

01.164p+8         01.164P+8
01.164p8          01.164P8
011640p-4         011640P-4

八进制浮点字面量(带“0o”前缀)(需要 v5.34.0)

0o1.164p+8        0O1.164P+8
0o1.164p8         0O1.164P8
0o11640p-4        0O11640P-4

二进制浮点字面量

0b1.0011101p+8    0B1.0011101P+8
0b1.0011101p8     0B1.0011101P8
0b10011101000p-2  0B10011101000P-2

性能

使用 $x += $y; 等形式比 $x = $x + $y 更快,因为在第二种情况下必须复制 $x。对于长数字,复制可能会占用多达 20% 的工作量(在加法/减法的情况下,乘法/除法更少)。如果 $y 比 $x 小得多,则 $x += $y 的形式比 $x = $x + $y 快得多,因为复制 $x 所花费的时间比实际加法更多。

通过一种称为写时复制的技术,可以最大限度地减少或甚至完全避免复制的成本。COW 的测试实现确实显示了重载数学的性能提升,但由于所有其他操作的恒定开销,导致了性能损失。因此,Math::BigInt 目前没有 COW。

此模块的重写版本(与 v0.01 相比)在某些操作(如 new()bstr()numify())上速度较慢。原因是它现在做了更多工作,并且处理了更多情况。在这些操作中花费的时间通常会在其他数学运算中获得,因此代码平均应该会(更快)。如果它们没有,请联系作者。

对于小数,某些操作可能较慢,但对于大数而言,速度明显更快。其他操作现在是恒定的(O(1),如 bneg()babs() 等),而不是 O(N),因此几乎总是花费更少的时间。这些优化是故意进行的。

如果你发现 Calc 模块速度很慢,请尝试安装任何替换模块,看看它们是否有帮助。

替代数学库

您可以使用替代库来驱动 Math::BigInt。有关更多信息,请参见 "MATH LIBRARY" 部分。

有关更多基准测试结果,请参见 http://bloodgate.com/perl/benchmarks.html

子类化

子类化 Math::BigInt

Math::BigInt 的基本设计允许简单地子类化,只需很少的工作,只要遵循一些简单的规则。

更复杂的子类可能需要复制 Math::BigInt 内部更多的逻辑,如果它们需要更改更基本的行为。只需要更改输出的子类只需要重载 bstr()

所有其他对象方法和重载函数都可以直接从父类继承。

至少,任何子类都需要提供自己的 new(),并且可以在对象中存储额外的哈希键。还有一些必须定义的包全局变量,例如:

# Globals
$accuracy = undef;
$precision = -2;       # round to 2 decimal places
$round_mode = 'even';
$div_scale = 40;

此外,您可能希望提供以下两个全局变量,以允许自动升级和自动降级正常工作

$upgrade = undef;
$downgrade = undef;

这允许 Math::BigInt 正确地从子类检索包全局变量,例如 $SubClass::precision。请参见 t/Math/BigInt/Subclass.pm 或 t/Math/BigFloat/SubClass.pm 以获取完全功能的子类示例。

不要忘记

use overload;

在您的子类中,以自动从父类继承重载。如果您愿意,可以更改重载的一部分,请查看 Math::String 以获取示例。

升级

当像这样使用时

use Math::BigInt upgrade => 'Foo::Bar';

某些操作会“升级”它们的计算,从而将结果升级到类 Foo::Bar。通常,这与 Math::BigFloat 结合使用。

use Math::BigInt upgrade => 'Math::BigFloat';

作为快捷方式,您可以使用模块 bignum

use bignum;

也适用于单行代码

perl -Mbignum -le 'print 2 ** 255'

这使得混合不同类的参数(如 2.5 + 2)以及保留精度(如 sqrt(3))成为可能。

注意:此功能尚未完全实现。

自动升级

以下方法无条件地自行升级;也就是说,如果升级生效,它们总是会放弃工作。

div bsqrt blog bexp bpi bsin bcos batan batan2

所有其他方法仅在它们的一个(或所有)参数属于 $upgrade 中提到的类时才自行升级。

EXPORTS

Math::BigInt 默认不导出任何内容,但可以导出以下方法

bgcd
blcm

注意事项

有些事情可能无法按预期工作。以下是已知存在问题的记录。

将数字作为字符串比较

bstr()bsstr() 以及通过重载进行字符串化都会删除前导 '+'. 这样做是为了与 Perl 保持一致,并使 cmp(尤其是与重载一起使用时)按预期工作。它还解决了 Test.pmTest::More 的问题,它们在比较参数之前会将参数字符串化。

Mark Biggar 在被问及是否要完全删除 '+' 或只让 cmp 工作时说

I agree (with the first alternative), don't add the '+' on positive
numbers.  It's not as important anymore with the new internal form
for numbers.  It made doing things like abs and neg easier, but
those have to be done differently now anyway.

因此,以下示例现在按预期工作

use Test::More tests => 1;
use Math::BigInt;

my $x = Math::BigInt -> new(3*3);
my $y = Math::BigInt -> new(3*3);

is($x,3*3, 'multiplication');
print "$x eq 9" if $x eq $y;
print "$x eq 9" if $x eq '9';
print "$x eq 9" if $x eq 3*3;

此外,以下内容仍然有效

print "$x == 9" if $x == $y;
print "$x == 9" if $x == 9;
print "$x == 9" if $x == 3*3;

现在有一个 bsstr() 方法可以获取科学记数法的字符串,例如 1e+2 而不是 100。请注意,重载的 'eq' 始终使用 bstr() 进行比较,但 Perl 将某些数字表示为 100,而将其他数字表示为 1e+308。如有疑问,请将两个参数都转换为 Math::BigInt,然后再将它们作为字符串进行比较。

use Test::More tests => 3;
use Math::BigInt;

$x = Math::BigInt->new('1e56');
$y = 1e56;
is($x,$y);                     # fails
is($x->bsstr(), $y);           # okay
$y = Math::BigInt->new($y);
is($x, $y);                    # okay

或者,只需使用 <=> 进行比较,这总是能得到正确的结果。目前还没有一种方法可以自动将数字表示为与 Perl 表示方式完全匹配的字符串。

另请参阅有关 "无穷大和非数字" 的部分,了解比较 NaN 时的问题。

int()

int() 返回(至少对于 Perl v5.7.1 及更高版本)另一个 Math::BigInt,而不是 Perl 标量。

$x = Math::BigInt->new(123);
$y = int($x);                           # 123 as a Math::BigInt
$x = Math::BigFloat->new(123.45);
$y = int($x);                           # 123 as a Math::BigFloat

如果您想要一个真正的 Perl 标量,请使用 numify()

$y = $x->numify();                      # 123 as a scalar

不过,这很少有必要,因为这是自动完成的,例如当您访问数组时。

$z = $array[$x];                        # does work automatically
修改和 =

注意

$x = Math::BigFloat->new(5);
$y = $x;

这会对相同对象进行第二次引用并将其存储在 $y 中。因此,任何修改 $x 的操作(除了重载运算符)也会修改 $y,反之亦然。换句话说,= 只有在您仅通过重载数学运算来修改 Math::BigInt 对象时才是安全的。一旦您使用方法调用,它就会失效。

$x->bmul(2);
print "$x, $y\n";       # prints '10, 10'

如果您想要 $x 的真实副本,请使用

$y = $x->copy();

您也可以像这样链接调用,这首先会创建一个副本,然后将其乘以 2

$y = $x->copy()->bmul(2);

另请参阅 overload.pm 文档,了解有关 = 的信息。

重载 -$x

以下

$x = -$x;

$x->bneg();

慢,因为 overload 调用 sub($x,0,1); 而不是 neg($x)。第一个变体需要保留 $x,因为它不知道它稍后会被覆盖。这会创建 $x 的副本并花费 O(N) 时间,但 $x->bneg() 是 O(1) 时间。

混合不同的对象类型

使用重载运算符,第一个(占主导地位)操作数决定调用哪个方法。以下是一些示例,展示了在各种情况下实际调用的内容。

use Math::BigInt;
use Math::BigFloat;

$mbf  = Math::BigFloat->new(5);
$mbi2 = Math::BigInt->new(5);
$mbi  = Math::BigInt->new(2);
                                # what actually gets called:
$float = $mbf + $mbi;           # $mbf->badd($mbi)
$float = $mbf / $mbi;           # $mbf->bdiv($mbi)
$integer = $mbi + $mbf;         # $mbi->badd($mbf)
$integer = $mbi2 / $mbi;        # $mbi2->bdiv($mbi)
$integer = $mbi2 / $mbf;        # $mbi2->bdiv($mbf)

例如,Math::BigInt->bdiv() 始终返回一个 Math::BigInt,无论第二个操作数是 Math::BigFloat 还是其他类型。要获得 Math::BigFloat,您需要手动调用操作,确保每个操作数已经是 Math::BigFloat,或者通过 Math::BigFloat->new() 转换为该类型。

$float = Math::BigFloat->new($mbi2) / $mbi;     # = 2.5

注意不要对整个表达式进行强制转换,因为这会强制转换结果,此时已经太迟了。

$float = Math::BigFloat->new($mbi2 / $mbi);     # = 2

还要注意更复杂表达式的顺序,例如

$integer = ($mbi2 + $mbi) / $mbf;               # int / float => int
$integer = $mbi2 / Math::BigFloat->new($mbi);   # ditto

如有疑问,请将表达式分解为更简单的项,或将所有操作数强制转换为所需的最终类型。

标量值略有不同,因为

$float = 2 + $mbf;
$float = $mbf + 2;

由于重载数学运算的工作方式,两者都会产生正确的类型。

本节也适用于其他重载数学包,例如 Math::String。

解决您问题的解决方案可能是自动升级|升级。有关执行此操作的简便方法,请参阅 bignumbigintbigrat 这些 pragma。

BUGS

请将任何错误或功能请求报告到 bug-math-bigint at rt.cpan.org,或通过网页界面报告到 https://rt.cpan.org/Ticket/Create.html?Queue=Math-BigInt(需要登录)。我们会收到通知,然后您会自动收到有关错误进展的通知,因为我会进行更改。

SUPPORT

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

perldoc Math::BigInt

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

LICENSE

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

SEE ALSO

Math::BigFloatMath::BigRat 以及后端 Math::BigInt::FastCalcMath::BigInt::GMPMath::BigInt::Pari

pragma bignumbigintbigrat 也可能很有趣,因为它们至少部分地解决了自动升级/降级问题。

AUTHORS

许多人以一种或多种方式为最终的野兽做出了贡献,请参阅 CREDITS 文件以获取(不完整的)列表。如果您错过了您的姓名,请给我发邮件。谢谢!