首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 浮點數取整函數完整指南:ceil、floor、round、intval 與精度陷阱

     編輯:PHP 相關知識

四大取整函數對比

函數行為回傳型別典型用途
ceil()向上取整 (天花板)float分頁計算、資源配額向上
floor()向下取整 (地板)float分頁索引、陣列索引
round()四捨五入 (可指定精度)float金額顯示、統計數據
intval()截斷小數 (向零取整)int型別轉換、ID 處理

詳細行為與範例

ceil() - 向上取整

<?php
echo ceil(4.3);    // 5
echo ceil(9.999);  // 10
echo ceil(-4.3);   // -4 (向上 = 更接近正無窮)
echo ceil(-9.999); // -9

// 實用:分頁總頁數
$totalItems = 103;
$perPage = 20;
$totalPages = (int) ceil($totalItems / $perPage); // 6
?>

floor() - 向下取整

<?php
echo floor(4.3);    // 4
echo floor(9.999);  // 9
echo floor(-4.3);   // -5 (向下 = 更接近負無窮)
echo floor(-9.999); // -10

// 實用:陣列隨機索引
$items = ['a', 'b', 'c', 'd', 'e'];
$randomIndex = (int) floor(mt_rand() / mt_getrandmax() * count($items));
?>

round() - 四捨五入 (支援精度)

<?php
// 基本四捨五入
echo round(3.4);     // 3
echo round(3.5);     // 4 (PHP 採用「銀行家捨入法」: .5 向偶數)
echo round(3.6);     // 4

// 指定小數位數
echo round(1.95583, 2);   // 1.96
echo round(1241757, -3);  // 1242000 (負精度 = 整數位捨入)

// 銀行家捨入法示例
echo round(0.5);  // 0 (偶數)
echo round(1.5);  // 2 (偶數)
echo round(2.5);  // 2 (偶數)
echo round(3.5);  // 4 (偶數)

// PHP 8.0+ 可指定模式
echo round(1.5, 0, PHP_ROUND_HALF_UP);   // 2 (傳統四捨五入)
echo round(1.5, 0, PHP_ROUND_HALF_DOWN); // 1
echo round(1.5, 0, PHP_ROUND_HALF_EVEN); // 2 (預設,銀行家)
?>

intval() - 截斷轉整數

<?php
echo intval(4.3);    // 4
echo intval(4.6);    // 4 (直接截斷,非四捨五入)
echo intval(-4.3);   // -4 (向零)
echo intval(-4.6);   // -4

// 字串轉換規則
echo intval('123');        // 123
echo intval('123abc');     // 123 (遇非數字停止)
echo intval('abc123');     // 0 (開頭非數字)
echo intval('-123');       // -123
echo intval('1.9');        // 1 (小數點視為非數字)

// 基數轉換 (第二參數)
echo intval('1010', 2);    // 10 (二進制)
echo intval('FF', 16);     // 255 (十六進制)
echo intval('77', 8);      // 63 (八進制)
?>

浮點數精度陷阱 (必讀)

<?php
// 經典問題
echo 0.1 + 0.2;        // 0.30000000000000004
echo floor(0.1 + 0.2); // 0 (非預期的 0!)
echo intval(0.1 + 0.2); // 0

// 原因:IEEE 754 二進制無法精確表示 0.1、0.2
// 解決方案:

// 1. BCMath 高精度數學 (推薦金融計算)
echo bcadd('0.1', '0.2', 2);      // 0.30
echo bcmul('19.99', '100', 0);    // 1999 (分為單位)

// 2. 整數運算 (以分/毫為單位)
$priceCents = 1999; // 19.99 元
$quantity = 3;
$totalCents = $priceCents * $quantity; // 5997 分 = 59.97 元

// 3. round() 修正顯示
echo round(0.1 + 0.2, 2); // 0.3

// 4. number_format 格式化輸出
echo number_format(0.1 + 0.2, 2); // "0.30"
?>

金融/電商計算最佳實踐

<?php
class Money {
    private int $cents; // 內部以最小單位 (分) 儲存
    
    public static function fromDollars(float|string $dollars): self {
        $cents = (int) round((float) $dollars * 100);
        return new self($cents);
    }
    
    public function __construct(int $cents) {
        $this->cents = $cents;
    }
    
    public function add(self $other): self {
        return new self($this->cents + $other->cents);
    }
    
    public function multiply(float $factor): self {
        return new self((int) round($this->cents * $factor));
    }
    
    public function toDollars(int $decimals = 2): string {
        $dollars = $this->cents / 100;
        return number_format($dollars, $decimals, '.', ',');
    }
    
    public function __toString(): string {
        return $this->toDollars();
    }
}

// 使用
$price = Money::fromDollars('19.99');
$total = $price->multiply(3)->add(Money::fromDollars('5.00'));
echo $total; // "64.97"
?>

函數選擇決策樹

需要四捨五入到指定小數位?
├─ 是 → round($val, $precision) [PHP 8+ 可指定模式]
└─ 否
   ├─ 需向上取整? → ceil($val)
   ├─ 需向下取整? → floor($val)
   ├─ 需轉為整數型別? → (int) $val 或 intval($val)
   └─ 金融計算? → BCMath / 整數分單位 / Money 物件

常見錯誤對照表

程式碼結果問題修正
(int) (19.99 * 100)1998浮點誤差導致截斷(int) round(19.99 * 100)
floor(0.1 + 0.2)0浮點誤差floor(bcadd('0.1', '0.2', 10))
round(2.5)2銀行家捨入法round(2.5, 0, PHP_ROUND_HALF_UP)
intval('1.9')1字串遇點停止(int) round('1.9')

理解浮點數本質與各函數行為差異,選擇正確工具處理數值,是避免生產環境離奇 Bug 的關鍵。金融計算請務必使用整數分單位或 BCMath。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved