PHP 浮點數存在精度缺失(0.1 + 0.7 = 0.799999...),財務、科學計算必須用 BCMath 任意精度數學擴展。本文整理全函數表、參數詳解、實戰代碼模式與常見陷阱。
$scale 參數控制結果小數位,全局預設由 bcscale() 設定。| 函數 | 功能 | 簽名 | 示例 |
|---|---|---|---|
| bcadd | 加法 | bcadd(string $left, string $right, int $scale=null): string | bcadd('1.234', '5.678', 2) → '6.91' |
| bcsub | 減法 | bcsub(string $left, string $right, int $scale=null): string | bcsub('10.5', '3.2', 1) → '7.3' |
| bcmul | 乘法 | bcmul(string $left, string $right, int $scale=null): string | bcmul('0.1', '0.2', 2) → '0.02' |
| bcdiv | 除法 | bcdiv(string $left, string $right, int $scale=null): string | bcdiv('10', '3', 4) → '3.3333' |
| bcmod | 取模 | bcmod(string $left, string $right, int $scale=null): string | bcmod('10', '3') → '1' |
| bcpow | 冪 | bcpow(string $base, string $exp, int $scale=null): string | bcpow('2', '10') → '1024' |
| bcpowmod | 模冪 (數論核心) | bcpowmod(string $base, string $exp, string $mod, int $scale=null): string | bcpowmod('2', '100', '101') → '1' |
| bcsqrt | 平方根 | bcsqrt(string $num, int $scale=null): string | bcsqrt('2', 10) → '1.4142135623' |
| bccomp | 比較 | bccomp(string $left, string $right, int $scale=null): int | 返回 -1/0/1,類比 strcmp |
| bcscale | 設定全局預設 scale | bcscale(int $scale): bool | bcscale(4); 後續省略 scale 參數 |
<?php
// 1. 初始化全局精度(如財務 4 位小數)
bcscale(4);
// 2. 封裝工具類(建議)
class BCMathCalc {
public static function add(string $a, string $b, int $scale = null): string {
return bcadd($a, $b, $scale ?? 4);
}
public static function sub(string $a, string $b, int $scale = null): string {
return bcsub($a, $b, $scale ?? 4);
}
// ... 其他運算
public static function cmp(string $a, string $b, int $scale = null): int {
return bccomp($a, $b, $scale ?? 4);
}
}
// 3. 使用示例:連續扣款
$balance = '134.7';
$balance = BCMathCalc::sub($balance, '52.5'); // 82.2
$balance = BCMathCalc::sub($balance, '82.2'); // 0.0
echo $balance; // "0.0000"
// 4. 比較判斷
if (BCMathCalc::cmp($balance, '0') === 0) {
echo "餘額歸零";
}
| 陷阱 | 現象 | 解決 |
|---|---|---|
| 直接用 float 字面量 | bcadd(0.1, 0.2) → 參數被轉為字符串 "0.1" "0.2" 仍正確,但複雜表達式可能先發生浮點運算 | 全部用字符串字面量:bcadd('0.1', '0.2') |
| scale 參數缺失導致截斷 | bcdiv('1', '3') → '0' (scale=0) | 顯式傳 scale 或 bcscale() 設定預設 |
| 負數字符串格式 | '-1.5' 合法,'+1.5' 非法 | 統一去除正號 |
| 科學計數法字符串 | '1.2E-5' 不支援 | 先轉為定點字符串 |
| 極大數字效能 | 萬位以上乘冪明顯變慢 | 考慮 GMP 擴展 (資源型別) 或分治算法 |
gmp_*、支援位運算、質數測試、隨機數、效能略優、適合密碼學/數論。+ * 等),BCMath 仍需函數調用。<?php
if (!extension_loaded('bcmath')) {
die('BCMath extension required. Install: apt/php-yum install php-bcmath');
}
echo "BCMath OK\n";
牢記「字符串進、字符串出、scale 必傳」,BCMath 即可成為 PHP 高精度計算的穩固基石。