紀錄工作經驗、相關知識,解決技術相關問題。

Javascript, React, 新手 Jamp Holes, 網站相關

JS 無條件進位 Math.ceil 計算:無條件進位小數點第 N 位、十位數與分頁總頁數計算範本

JS 無條件進位 Math.ceil 計算:無條件進位小數點第 N 位、十位數與分頁總頁數計算範本 特色圖片

在前端表單與電商金額計算中,經常需要使用 JavaScript 的 Math.ceil 無條件進位將帶有小數的數值向上取整。由於原生 Math.ceil() 僅支援整數進位,若要處理「無條件進位到小數點第二位」或「十位數進位」,則需結合倍率位移公式;計算完成後若需加上逗號顯示,可進一步搭配 JS 數字加逗號與轉換千分位顯示 進行格式化。

⚡ 快速跳轉(依實務情境選擇):


一、 核心複製即用範本與無條件進位公式對照表

在 JavaScript 中,Math.ceil(x) 會回傳大於或等於 x 的最小整數(朝正無限大 +∞ 方向取整)。以下整理實務開發最常使用的 4 種無條件進位情境與對應公式:

進位需求情境計算公式寫法輸入範例輸出結果
基本整數無條件進位Math.ceil(num)9.0110
負數無條件進位(朝 0 靠近)Math.ceil(num)-9.5-9
無條件進位到小數點第 2 位Math.ceil(num * 100) / 1001.1411.15
無條件進位到整數十位數Math.ceil(num / 10) * 10123130

二、 通用位數無條件進位函式(ceilByDigits)

為了處理 IEEE 754 浮點數運算產生的微小誤差(如 1.14 * 100 可能變成 113.99999999999999),建議在位移計算時加入 toPrecision(15) 進行修正。以下提供支援正負位數(小數點或十百千位)的通用封裝函式:

/**
 * 指定位數無條件進位
 * @param {number} num 原始數值
 * @param {number} digits 進位到小數點第幾位 (正數為小數點後,負數為整數位)
 */
function ceilByDigits(num, digits = 0) {
  const factor = Math.pow(10, digits);
  // 先放大、修正浮點數誤差、進位、再縮小
  return Math.ceil(Number((num * factor).toPrecision(15))) / factor;
}

// 實測範例
console.log(ceilByDigits(1.141, 2));   // 1.15 (小數點第二位)
console.log(ceilByDigits(123.45, -1)); // 130  (十位數)
console.log(ceilByDigits(123.45, -2)); // 200  (百位數)

三、 分項語法拆解與應用場景實作

1. 基本整數與正負數進位規則

Math.ceil() 的核心邏輯是「向上取整」,這在處理負數時與 Math.floor() 或 Math.trunc() 的行為不同:

  • 正數:Math.ceil(1.2) 得到 2。
  • 負數:Math.ceil(-1.2) 得到 -1(因為 -1 大於 -1.2)。

若你的需求是「不論正負,一律遠離 0 進位」(例如 -1.2 變 -2),則需判斷正負號後改用 Math.abs() 搭配 Math.ceil()。

2. 指定小數點第 N 位無條件進位與浮點數誤差防範

直接使用 num * 100 容易踩到 JavaScript 精度陷阱。例如:
Math.ceil(1.14 * 100) / 100 理論上應為 1.14,但若 1.14 * 100 變成 114.00000000000001,結果會變成 1.15。

解法思路:
使用 toPrecision(15) 將數值強制轉回最接近的精確值後再進行 Math.ceil,可確保在 99.9% 的商業計算中結果正確。

3. 列表分頁總頁數計算(Pagination Total Pages)

這是 Math.ceil 最經典的應用場景。當我們從後端取得總資料筆數,並根據前端設定的每頁顯示數量時,總頁數必須無條件進位。

const totalItems = 45; // 總共有 45 筆資料
const itemsPerPage = 10; // 每頁顯示 10 筆

// 計算總頁數
const totalPages = Math.ceil(totalItems / itemsPerPage); 

console.log(totalPages); // 輸出 5 (最後一頁只有 5 筆也算一頁)

在處理分頁導覽時,若需要根據當前網址參數決定起始頁面,可參考 [JS] Javascript 取得目前 URL 與相關參數(總整理) 來解析 page 參數。


四、 常見問題與排錯 Q&A

Q1:Math.ceil() 與 Math.round()、Math.floor() 有什麼差別?

  • Math.ceil():無條件進位(向上取整)。
  • Math.floor():無條件捨去(向下取整)。
  • Math.round():四捨五入。
  • Math.trunc():直接去掉小數部分(在正數時等同 floor,負數時等同 ceil)。

Q2:為什麼 Math.ceil("10.5") 可以運作?

JavaScript 會在執行 Math 方法前,自動嘗試將字串透過隱含轉型變為數字。但為了程式碼健壯性,建議先使用 Number() 進行顯式轉換,避免傳入非數字字串導致 NaN。

Q3:如何處理無條件進位後的金額格式化?

進位後的數值通常是 Number 型別,若要顯示在 UI 上並加上千分位逗號,建議使用 Intl.NumberFormat:

const price = Math.ceil(1234.5); // 1235
const formatted = new Intl.NumberFormat('zh-TW').format(price); // "1,235"

Q4:Math.ceil() 會處理 NaN 或 Infinity 嗎?

  • 若傳入 NaN,結果為 NaN。
  • 若傳入 Infinity 或 -Infinity,結果維持原樣。
  • 若傳入 null,會被轉為 0,結果為 0。

參考資料與延伸閱讀

發佈留言