timg/decimal

0.1 2018-06-24 20:46 UTC

This package is not auto-updated.

Last update: 2024-09-15 05:44:35 UTC


README

Decimal

PHP 是开发商业应用的流行语言。通常这类应用需要计算数字,例如处理金钱时。

尽管 PHP 是一种高级编程语言,处理像金钱这样的东西容易出错,并且通常实现不正确。其中一个原因是因为 PHP 没有内置的 Decimal 类型。人们通常使用浮点数来执行此类计算。如果你查看 浮点文档,会发现一个巨大的警告

所以永远不要相信浮点数的结果精确到小数点后最后一位,并且不要直接比较浮点数是否相等。

很容易犯这样的错误,即使这仅仅影响 最后一位,这也可能导致一个巨大且难以修复的问题。

如果你只想计算一个价格,或者做一些基本的数学运算,你可能根本不需要考虑 浮点运算

Decimal 类型

此包包含 DecimalDecimal[0-100] 类,其中 0-100 表示精度。这允许你编写类似 (new Decimal2("1.99"))->add(new Decimal2("1.99")) 的代码。还有辅助函数来创建 Decimal:dec2("1.99")->add(dec2("1.99"))。函数 dec2 返回一个 Decimal2dec99 可以返回一个 Decimal99 的实例。

有理数

此包还包含有理数类型。这可以帮助你执行诸如 3 * (1/3) 这样的计算。使用有理数类型,你可以简单地编写 Rational::fromDecimal(dec0(3))->mul(new Rational(dec0(1), dec0(3))。还有一个 rat() 函数,看起来更美观。

延迟计算

你可以将 1 + 2 表示为 3,但对于更复杂的数字,如 Rational 类型,这并不适用。例如,没有损失精度,你不能将 1/3 表示为十进制数。延迟计算的原理是,不是直接计算数字,而是记住计算步骤,并在尽可能晚的时候进行计算。

让我们来看一个小例子

$calculation = lazy_calc(dec(0))
    ->add(lazy_calc(rat(1, 3))->round(2))
    ->add(lazy_calc(rat(1, 3))->round(2))
    ->add(lazy_calc(rat(1, 3))->round(3));

static::assertSame(
    '(((0 + round((1 / 3), scale = 2)) + round((1 / 3), scale = 2)) + round((1 / 3), scale = 3))',
    $calculation->pretty()
);

如你所见,$calculation 只记录了完整的计算过程。你现在可以对计算做不同的事情,例如打印出来或使用不同的计算器来计算结果。

还可以为数字和计算步骤添加提示,并用注释美化计算过程。

这使得理解复杂的计算变得非常容易。例如,如果你需要计算包含许多不同项目、折扣、条件等的购物车,这将非常有用。如果你可以简单地注释并解释所有计算步骤,调试购物车将会容易得多。