除了舍入数字之外,round()还做了什么?

Han*_*etz 4 php floating-point arithmetic-expressions

我只是"修复"以下几行PHP中的错误:

        $value = 1091.09; // the failing test case
        $prop = sprintf('%013d', $value * 100);
Run Code Online (Sandbox Code Playgroud)

通过添加这些行:

        $cents = $value * 100; // $cents is now 109109
        $cents = round($cents, 2); // $cents is still 109109
        $prop = sprintf('%013d', $cents);
Run Code Online (Sandbox Code Playgroud)

前一个块的结果是"0000000109108",而第二个块的结果"0000000109109"是正确的.

请注意,我添加了两行,以便能够分别查看调试器中的每个步骤.如果我跳过第一行,它也有效,因此写道:

        $cents = round($value * 100, 2); // $cents is now 109109
        $prop = sprintf('%013d', $cents);
Run Code Online (Sandbox Code Playgroud)

因此,显然,该round()函数会对值进行某些操作,使其以不同的方式工作sprintf().它是什么?

如果这是一种恰当的语言,我可能会通过查看数据类型来了解.在这里,我甚至都不知道它们是什么.

Mih*_*ncu 6

要点:

初始数据类型为float64.

乘以100后,它仍然是一个浮点数.

打印(使用echo/print_r/var_dump)该值不会打印绝对精确值(109108.9999999999999); 它会打印近似的浮点值,109109因为浮点数本身就是近似值而不是精确值.

使用sprintf将其作为int打印会触发类型转换为int,从而截断109108.9999999999999to 的值109108.

因此你的问题.


作为旁注:

PHP支持的基本类型是使用处理程序变量和引用计数容器构造的.除此之外,他们是相当低级的东西.

没有理由认为它们比它们出现的"更复杂".我开始考虑复杂的对象而不是标量数据类型.

另外一个很大的混淆因素是(隐式)类型转换和所有类型转换规则(包括可以作为布尔值传递的所有内容).

第Ex.I:

  -1 == false // true
null == false // true
  -1 != null  // false
Run Code Online (Sandbox Code Playgroud)

例2:

0  == false // true
0 === false // false
Run Code Online (Sandbox Code Playgroud)