對于這段代碼:$value = 200.1;$denominator = 0.1;echo "value: $value\n";echo "denominator: $denominator\n";$resultInt = ($value / $denominator);echo "($value / $denominator) = ";printf ("%f\n", $resultInt);$resultInt = (int) ($value / $denominator);echo "(int) ($value / $denominator) = ";printf ("%f\n", $resultInt);$resultInt = floor($value / $denominator);echo "floor($value / $denominator) = ";printf ("%f\n", $resultInt);$resultInt = floor((int) ($value / $denominator));echo "floor((int) ($value / $denominator)) = ";printf ("%f\n", $resultInt);$resultInt = floor((float) 2001);echo "floor((float) 2001) = ";printf ("%f\n", $resultInt);$resultInt = round($value / $denominator, PHP_ROUND_HALF_DOWN);echo "round($value / $denominator, PHP_ROUND_HALF_DOWN) = ";printf ("%f\n", $resultInt);$valueMul = $resultInt * $denominator;if ($valueMul !== $value) { echo "they are not the same\n"; var_dump($value); var_dump($valueMul);}$valueDiff = $value - $valueMul;if ($valueDiff !== 0) { echo "valueDiff is not zero\n"; var_dump($valueDiff);}我有這個結果:value: 200.1denominator: 0.1(200.1 / 0.1) = 2001.000000(int) (200.1 / 0.1) = 2000.000000floor(200.1 / 0.1) = 2000.000000floor((int) (200.1 / 0.1)) = 2000.000000floor((float) 2001) = 2001.000000round(200.1 / 0.1, PHP_ROUND_HALF_DOWN) = 2001.000000they are not the samefloat(200.1)float(200.1)valueDiff is not zerofloat(-2.8421709430404E-14)上述所有計算的預期結果是 2001,但在某些情況下它是 2000。我知道由于計算機在二進制上運行,因此分數不會以小數形式存儲在變量中。但正如地板手冊所述:地板 -向下舍入分數因此我期望得到與以下相同的結果:round(200.1 / 0.1, PHP_ROUND_HALF_DOWN)但 round 按預期返回 2001,而下限返回 2000(錯誤)。你知道為什么嗎?我還發現這var_debug是不一致的:
1 回答

慕斯王
TA貢獻1864條經驗 獲得超2個贊
您遇到了精度問題。在 PHP 中,您永遠不應該相信浮點數的最后一位數字。
從手冊(浮點數)中,第二段甚至有關于您的特定測試數字的一點:
浮點數的精度有限。雖然這取決于系統,但 PHP 通常使用 IEEE 754 雙精度格式,由于按 1.11e-16 的順序舍入,這將給出最大相對誤差。非初等算術運算可能會產生較大的誤差,當然,當多個運算復合時,必須考慮誤差傳播。
此外,可以精確表示為以 10 為基數的浮點數的有理數(例如 0.1 或 0.7),沒有精確表示為以 2 為基數的浮點數(無論尾數的大小如何,在內部使用)。因此,它們無法在不損失少量精度的情況下轉換為內部二進制對應項。這可能會導致令人困惑的結果:例如,floor((0.1+0.7)*10) 通常會返回 7 而不是預期的 8,因為內部表示類似于 7.9999999999999991118...
因此,永遠不要相信浮點數結果到最后一位,也不要直接比較浮點數是否相等。如果需要更高的精度,可以使用任意精度數學函數和 gmp 函數。
- 1 回答
- 0 關注
- 103 瀏覽
添加回答
舉報
0/150
提交
取消