<?php
$a = 1.234; // 標準浮點
$b = 1.2e3; // 科學記號 = 1200
$c = 7E-10; // 科學記號 = 0.0000000007
?>
<?php
echo 0.1 + 0.2; // 0.30000000000000004
echo (0.1 + 0.2) === 0.3; // false
// 跨平台不一致
var_dump(1.234567890123456789); // 可能輸出 1.2345678901235
?>
原因:IEEE 754 雙精度浮點數無法精確表示十進位小數 (如 0.1)。
<?php
// 1. 設定容差 (epsilon)
function floatEquals($a, $b, $epsilon = 1e-10) {
return abs($a - $b) < $epsilon;
}
// 2. BCMath 字串比較 (任意精度)
function floatEqualsBC($a, $b, $scale = 10) {
return bccomp($a, $b, $scale) === 0;
}
// 3. sprintf 格式化後比較字串 (不推薦)
?>
| 擴充 | 特點 | 適用場景 |
|---|---|---|
| BCMath | 字串運算、任意精度、函數式 API (bcadd, bcmul, bcdiv, bccomp...) | 金融、貨幣、精確小數 |
| GMP | 整數運算、任意大小、支援位運算、物件導向 (PHP 8.1+) | 大整數、密碼學、組合數學 |
| Decimal (PHP 8.3+ 提案) | 原生十進位浮點、IEEE 754-2008 decimal128 | 未來標準 |
<?php
// 價格計算:單價 * 數量 + 稅
$price = '19.99';
$qty = '3';
$tax = '0.05';
$subtotal = bcmul($price, $qty, 2); // 59.97
$taxAmt = bcmul($subtotal, $tax, 2); // 3.00
$total = bcadd($subtotal, $taxAmt, 2); // 62.97
echo "總計: $total"; // 62.97 (精確)
?>
"123.45abc" → 123.45**金融/計費/庫存等精確度敏感業務,嚴禁直接使用 float 運算**。請統一採用 BCMath (小數) 或 GMP (大整數),資料庫欄位用 DECIMAL(precision, scale) 儲存。