此包已被废弃且不再维护。作者建议使用 brick/math 包。

任意精度算术库

0.6.0 2015-10-21 19:56 UTC

README

一个用于处理任意精度数字的库。

Build Status Coverage Status Latest Stable Version License

有关类和方法完整列表,请查看 API 文档

安装

此库可以通过 Composer 安装。只需在您的 composer.json 文件中定义以下要求即可

{
    "require": {
        "brick/math": "0.5.*"
    }
}

要求

此库需要 PHP 5.4、PHP 7 或 HHVM

尽管此库可以在任何 PHP 安装上无缝运行,但仍强烈建议您安装 GMPBCMath 扩展以加快计算速度。运行时会自动选择最快的可用计算器实现。

项目状态 & 发布流程

虽然此库仍在开发中,但经过了良好的测试,应该足够稳定,可以在生产环境中使用。

当前版本号格式为 0.x.y。当引入非破坏性更改(添加新方法、优化现有代码等)时,y 会递增。

当引入破坏性更改时,总是开始一个新的 0.x 版本周期。

因此,将您的项目锁定到给定的发布周期(如 0.5.*)是安全的。

如果您想使用最新版本,并接收任何非破坏性更新,请使用 ~0.5.2

如果您需要升级到较新的发布周期,请查看 发布历史 以了解每个后续 0.x.0 版本引入的更改列表。

包内容

此库在 Brick\Math 命名空间中提供了以下公共类

以及在 Brick\Math\Exception 命名空间中的以下异常

概述

实例化

类的构造函数不是公开的,您必须使用工厂方法来获取实例。

所有类都提供了一个of()工厂方法,该方法接受以下类型中的任何一种

  • BigNumber实例
  • int数字
  • float数字
  • 整数、小数和有理数的字符串表示

示例

BigInteger::of(123546);
BigInteger::of('9999999999999999999999999999999999999999999');

BigDecimal::of(1.2);
BigDecimal::of('9.99999999999999999999999999999999999999999999');

BigRational::of('2/3');
BigRational::of('1.1'); // 11/10

注意,所有of()方法都接受上述所有表示,只要它可以安全地转换为当前类型。

BigInteger::of('1.00'); // 1
BigInteger::of('1.01'); // ArithmeticException

BigDecimal::of('1/8'); // 0.125
BigDecimal::of('1/3'); // ArithmeticException

关于原生整数的说明:从int实例化是安全的,只要您不超过您的平台的最大值(PHP_INT_MAX),在这种情况下,PHP将透明地将它转换为float而不会发出通知,这可能导致信息丢失。如果有疑问,最好从字符串实例化,因为它支持无限位数的数字。

echo BigInteger::of(999999999999999999999); // 1000000000000000000000
echo BigInteger::of('999999999999999999999'); // 999999999999999999999

关于浮点数的说明:从float实例化可能不安全,因为浮点数是按设计不精确的,可能会丢失信息。始终首选从字符串实例化,它支持无限位数的数字。

echo BigDecimal::of(1.99999999999999999999); // 2
echo BigDecimal::of('1.99999999999999999999'); // 1.99999999999999999999

不可变性与链式操作

BigIntegerBigDecimalBigRational类是不可变的:它们的值永远不会改变,因此可以安全地传递。所有返回BigIntegerBigDecimalBigRational的方法都返回一个新的对象,而不会影响原始对象。

$ten = BigInteger::of(10);

echo $ten->plus(5); // 15
echo $ten->multipliedBy(3); // 30

方法可以链式调用,以提高可读性。

echo BigInteger::of(10)->plus(5)->multipliedBy(3); // 45

参数类型

所有接受数字的方法(如plus()minus()multipliedBy()等)接受的类型与of()相同。例如,给定以下数字

$integer = BigInteger::of(123);

以下行是等效的

$integer->multipliedBy(123);
$integer->multipliedBy('123');
$integer->multipliedBy($integer);

of()一样,其他类型的BigNumber也是可接受的,只要它们可以安全地转换为当前类型。

echo BigInteger::of(2)->multipliedBy(BigDecimal::of('2.0')); // 4
echo BigInteger::of(2)->multipliedBy(BigDecimal::of('2.5')); // ArithmeticException
echo BigDecimal::of(2.5)->multipliedBy(BigInteger::of(2)); // 5.0

除法与四舍五入

BigInteger

默认情况下,除以BigInteger返回除法的精确结果,或者如果除法的余数不为零,则抛出异常。

echo BigInteger::of(999)->dividedBy(3); // 333
echo BigInteger::of(1000)->dividedBy(3); // RoundingNecessaryException

如果需要,您可以传递一个可选的舍入模式来四舍五入结果。

echo BigInteger::of(1000)->dividedBy(3, RoundingMode::DOWN); // 333
echo BigInteger::of(1000)->dividedBy(3, RoundingMode::UP); // 334

如果您对商和余数感兴趣,也有针对这些的方法。

echo BigInteger::of(1000)->quotient(3); // 333
echo BigInteger::of(1000)->remainder(3); // 1

您甚至可以同时获得这两者。

list ($quotient, $remainder) = BigInteger::of(1000)->quotientAndRemainder(3);
BigDecimal

除以BigDecimal始终需要指定一个刻度。如果除法的精确结果不适合给定的刻度,必须提供舍入模式

echo BigDecimal::of(1)->dividedBy('8', 3); // 0.125
echo BigDecimal::of(1)->dividedBy('8', 2); // RoundingNecessaryException
echo BigDecimal::of(1)->dividedBy('8', 2, RoundingMode::HALF_DOWN); // 0.12
echo BigDecimal::of(1)->dividedBy('8', 2, RoundingMode::HALF_UP); // 0.13

如果您知道除法会产生有限的小数位数,您可以使用exactlyDividedBy(),它将自动计算所需的刻度以适应结果,或者如果除法产生无限循环小数,则抛出异常。

echo BigDecimal::of(1)->exactlyDividedBy(256); // 0.00390625
echo BigDecimal::of(1)->exactlyDividedBy(11); // RoundingNecessaryException
BigRational

BigRational 的除法结果总是可以精确表示

echo BigRational::of('123/456')->dividedBy('7'); // 123/3192
echo BigRational::of('123/456')->dividedBy('9/8'); // 984/4104

序列化

BigIntegerBigDecimalBigRational 可以在机器上安全地序列化,并在另一台机器上反序列化,即使这些机器不共享相同的 PHP 扩展集。

例如,在支持 GMP 的机器上序列化,并在未安装此扩展的机器上反序列化,仍会按预期工作。