您的代码中的数字都无法以二进制浮点数的形式
精确表示,它们都被四舍五入了。问题在于为什么一个结果(看起来)被四舍五入到两位小数,而另一个没有。答案在于浮点数的
精度和
准确性以及 PHP 用于打印它们的精度之间的差异。
浮点数由范围在[1, 2)
内的有效数字(或尾数)表示,通过将其乘以二的幂进行缩放。(这就是浮点中“浮动”的含义)。数字的精度由有效数字中的数字数量确定。其准确性取决于其中有多少位数字实际上是正确的。有关更多详细信息,请参见:浮点数在内存中如何存储?。
当你在PHP中使用
echo
输出浮点数时,它们会首先使用
precision
配置设置转换为字符串,该设置默认为14。(在
Zend/zend_operators.c
中)
要查看实际发生的情况,您需要使用更大的精度打印数字:
$aa = 10694994.89;
$bb = 10696193.86;
$ab = $aa - $bb;
printf ("\$aa: %.20G\n", $aa);
printf ("\$bb: %.20G\n", $bb);
printf ("\$ab: %.20G\n\n", $ab);
$cc = 0.89;
$dd = 0.86;
$cd = $cc - $dd;
printf ("\$cc: %.20G\n", $cc);
printf ("\$dd: %.20G\n", $dd);
printf ("\$cd: %.20G\n", $cd);
输出:
$aa: 10694994.890000000596
$bb: 10696193.859999999404
$ab: -1198.9699999988079071
$cc: 0.89000000000000001332
$dd: 0.85999999999999998668
$cd: 0.030000000000000026645
初始数字精度约为16到17位。当你减去
$aa-$bb
时,前4位数字会互相抵消。结果(虽然仍然具有约16到17位的精度)现在只有大约12位是
准确的。当使用14位精度打印结果时,这种较低的准确性就会显现出来。
另一个减法(
$cc-$dd
)只失去了一位数字的准确性,在使用14位精度打印时不明显。