四大核心取整函數對照
| 函數 | 行為 | 返回類型 | 適用場景 | 典型範例 |
ceil($val) | **向上取整**(天花板) | float | 分頁總頁數、資源配額向上分配 | ceil(4.3)=5, ceil(-4.3)=-4 |
floor($val) | **向下取整**(地板) | float | 分頁偏移量、索引計算、向下分配 | floor(4.9)=4, floor(-4.9)=-5 |
round($val, $precision=0, $mode=PHP_ROUND_HALF_UP) | **四捨五入**(支援精度與模式) | float | 金額顯示、統計報表、測量數據 | round(3.14159,2)=3.14, round(1.5)=2 |
intval($val, $base=10) | **截斷轉整數**(向零取整) | int | ID 轉換、陣列索引、位運算前置 | intval(4.9)=4, intval(-4.9)=-4 |
關鍵差異:負數處理與返回類型
<?php
$nums = [4.3, 4.9, -4.3, -4.9];
foreach ($nums as $n) {
echo "{$n}: ";
echo "ceil=" . ceil($n) . " ";
echo "floor=" . floor($n) . " ";
echo "round=" . round($n) . " ";
echo "intval=" . intval($n) . " ";
echo "gettype(ceil)=" . gettype(ceil($n)) . "\n";
}
/*
輸出:
4.3: ceil=5 floor=4 round=4 intval=4 gettype(ceil)=double
4.9: ceil=5 floor=4 round=5 intval=4 gettype(ceil)=double
-4.3: ceil=-4 floor=-5 round=-4 intval=-4 gettype(ceil)=double
-4.9: ceil=-4 floor=-5 round=-5 intval=-4 gettype(ceil)=double
*/
?>
核心差異:
- ceil/floor 返回 **float**(因 float 範圍大於 int)
- intval 返回 **int**(直接截斷小數,向零取整)
- round 支援 $precision(小數位)與 $mode(進位模式)
round 進位模式深度解析 (PHP 7.1+)
| 模式常數 | 行為 | 範例:round(1.5) | 範例:round(-1.5) |
PHP_ROUND_HALF_UP | 遠離零(傳統四捨五入) | 2 | -2 |
PHP_ROUND_HALF_DOWN | 趨向零 | 1 | -1 |
PHP_ROUND_HALF_EVEN | 銀行家進位(最近偶數) | 2 | -2 |
PHP_ROUND_HALF_ODD | 最近奇數 | 1 | -1 |
<?php
// 金融計算建議:銀行家進位減少統計偏差
$prices = [1.235, 1.245, 1.255, 1.265];
foreach ($prices as $p) {
echo "{$p} -> " . round($p, 2, PHP_ROUND_HALF_EVEN) . "\n";
}
// 1.235 -> 1.24 (4 是偶數)
// 1.245 -> 1.24 (4 是偶數)
// 1.255 -> 1.26 (6 是偶數)
// 1.265 -> 1.26 (6 是偶數)
?>
精度陷阱:浮點數運算不精確
<?php
// 經典陷阱
echo floor(0.1 + 0.7); // 預期 0,實際 0(0.7999999...)
echo intval(0.1 + 0.7); // 0
echo round(0.1 + 0.7, 1); // 0.8 (正確)
// 金額計算**嚴禁**用浮點數
$price = 19.99;
$qty = 3;
$total = $price * $qty; // 59.970000000000006
// 正確做法:BCMath 或整數分單位
// 1. BCMath 任意精度
echo bcmul('19.99', '3', 2); // 59.97
// 2. 整數分(分為單位存儲)
$priceCents = 1999;
$totalCents = $priceCents * 3; // 5997
echo $totalCents / 100; // 59.97
?>
進階函數:fmod、is_int、is_float、filter_var
| 函數 | 用途 | 範例 |
fmod($x, $y) | 浮點數取模(% 僅支援整數) | fmod(10.5, 3.2) = 0.9 |
is_int($val) / is_float() | 類型檢查(不檢查值) | is_int(5.0) = false |
filter_var($val, FILTER_VALIDATE_INT) | 驗證並轉換為整數 | filter_var('123', FILTER_VALIDATE_INT) = 123 |
number_format($val, $decimals, $dec_point, $thousands_sep) | 格式化數字輸出 | number_format(1234.56, 2, '.', ',') = '1,234.56' |
實戰最佳實踐
- 分頁計算:
$totalPages = (int)ceil($totalItems / $perPage)(轉 int 供嚴格類型)
- 金額存儲:資料庫用
DECIMAL(10,2) 或 **整數分** BIGINT,PHP 用 BCMath/整數運算
- 統計報表:
round($avg, 2, PHP_ROUND_HALF_EVEN) 減少累積偏差
- 類型轉換:
(int)$val 比 intval($val) 略快,但 intval 支援進制轉換
- 邊界測試:單元測試覆蓋
0, -0, 0.5, -0.5, 1.5, -1.5, PHP_INT_MAX, PHP_FLOAT_MAX
總結
PHP 取整函數看似簡單,實則暗藏負數行為差異、浮點精度陷阱、返回類型不一、進位模式選擇等細節。記住核心口訣:
🔹 向上 用 ceil(float)
🔹 向下 用 floor(float)
🔹 四捨五入 用 round(可控精度/模式,float)
🔹 截斷轉整數 用 intval / (int)(int,向零)
🔹 金額/高精度 **絕對不用浮點數**,改用 **BCMath** 或 **整數分單位**。
掌握這些,讓數值計算不再成為 Bug 溫床。
- 上一篇文章: PHP 超全域變數完整指南:$_GET、$_POST、$_REQUEST、$_FILES、$_COOKIE、$_SESSION、$_SERVER、$_ENV
- 下一篇文章: PHP 快取技術全景指南:從資料快取到靜態化的進階實戰
Copyright ©
程式碼之家 All Rights Reserved