我刚刚修复了以下几行PHP中的错误:
$value = 1091.09; // the failing test case
$prop = sprintf('%013d', $value * 100);
添加以下行:
$cents = $value * 100; // $cents is now 109109
$cents = round($cents, 2); // $cents is still 109109
$prop = sprintf('%013d', $cents);
前一个块的结果是"0000000109108"
,而第二个块的结果是"0000000109109"
,这是正确的。
请注意,我添加了两行,以便能够分别查看调试器中的每个步骤。如果我跳过第一行,它也有效,因此写道:
$cents = round($value * 100, 2); // $cents is now 109109
$prop = sprintf('%013d', $cents);
因此,显然,round()
函数会对值产生不可见的因素,使其与sprintf()
的工作方式不同。它是什么?
如果这是一种正确的语言,我可能会通过查看数据类型来了解。在这里,我甚至不知道它们是什么。
答案 0 :(得分:6)
初始数据类型为float64。
在乘以100之后,它仍然是浮动的。
打印(使用echo / print_r / var_dump)该值不会打印绝对精确值(109108.9999999999999
);它打印出近似浮点值109109
,因为浮点数本身就是近似值而不是精确值。
使用sprintf将其作为int 打印会触发将类型转换为int,从而将109108.9999999999999
的值截断为109108
。
因此你的问题。
PHP支持的基本类型是使用处理程序变量和引用计数容器构造的。除此之外,他们是非常低级的东西。
没有理由认为它们比它们出现的“更复杂”。我开始考虑复杂的对象而不是标量数据类型。
另一个很大的混淆因素是(隐式)类型转换和所有类型转换规则(包括可以作为布尔值传递的所有内容)。
实施例1,:
-1 == false // true
null == false // true
-1 != null // false
例2:
0 == false // true
0 === false // false
答案 1 :(得分:0)
它可能不那么简单......
php > $value = 1091.09; print sprintf('%f', $value);
1091.090000
php > $value = 1091.09; print sprintf('%f', $value*100);
109109.000000
php > $value = 1091.09; print sprintf('%f', (int)($value*100));
109108.000000
人们期望在前两个结果中看到所有这些'999999'。
此外:
php > $value = 0.09; print sprintf('%f', $value);
0.090000
php > $value = 0.09; print sprintf('%f', $value*100);
9.000000
php > $value = 0.09; print sprintf('%f', (int)($value*100));
9.000000
(NOTE: same result of 0.009 and 0.9)
底线,@ Mihai可能正好在his answer,但似乎这些“近似”浮点数(无限数量为99999)存在于浮点运算单元内部深处并影响PHP级别仅在某些非常特殊的情况下进行计算。