您的代码中没有一个数字可以准确地以二进制浮点数表示。它们都以某种方式被四舍五入。问题是为什么其中一个结果(似乎)被四舍五入到两位小数,而不是另一个。答案在于浮点数的 precision 和 accuracy 与 PHP 用于打印它们的精度之间的差异。
浮点数由[1, 2) 范围内的有效数(或尾数)表示,通过乘以2 的幂来缩放。 (这就是浮点中的“浮动”的意思)。数字的精度由有效位的位数决定。 准确度取决于这些数字中有多少实际上是正确的。请参阅:How are floating point numbers stored in memory? 了解更多详情。
当你在 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 位精度打印时并不明显。