PHP 浮點數遵循 IEEE 754 標準,二進制無法精確表示許多十進制小數(如 0.1、0.7),導致經典的 0.1 + 0.7 != 0.8 問題。本文深度解析精度丟失根因,並系統講解 BCMath 擴展提供的高精度運算函數族,附帶金融級計算最佳實踐。
<?php $a = 0.1; $b = 0.7; var_dump(($a + $b) == 0.8); // bool(false) ! // 實際內部值:0.7999999999999999... ?>
永遠不要相信浮點數結果精確到最後一位,也永遠不要直接比較兩個浮點數是否相等。若需高精度,請使用 BCMath 或 GMP 擴展。
BCMath (Binary Calculator) 以字符串形式表示任意精度數字,所有運算精確無誤差。
| 函數 | 功能 | 參數 |
|---|---|---|
| bcadd | 加法 | (string $left, string $right, int $scale=0) |
| bcsub | 減法 | (string $left, string $right, int $scale=0) |
| bcmul | 乘法 | (string $left, string $right, int $scale=0) |
| bcdiv | 除法 | (string $left, string $right, int $scale=0) |
| bcmod | 取模 | (string $left, string $modulus) |
| bcpow | 冪 | (string $left, string $right, int $scale=0) |
| bcpowmod | 冪取模 (數論常用) | (string $left, string $right, string $mod, int $scale=0) |
| bcsqrt | 平方根 | (string $operand, int $scale=0) |
| bccomp | 比較 (-1/0/1) | (string $left, string $right, int $scale=0) |
| bcscale | 設定全局默認小數位 | (int $scale) |
| 特性 | BCMath | GMP |
|---|---|---|
| 數字表示 | 字符串 (十進制) | 資源/對象 (二進制) |
| 性能 | 較慢 (字符串運算) | 極快 (C 底層優化) |
| 功能豐富度 | 基礎四則運算+開方 | 完整數論函數 (質數、因子、隨機等) |
| 安裝普及度 | PHP 內建常開啟 | 需額外編譯 --with-gmp |
金融、電商、計費等對精度零容忍場景,BCMath 是標準選擇;密碼學、大整數運算則首選 GMP。