JavaScript Tips | 数値・計算:数値を整数に丸める

JavaScript JavaScript
スポンサーリンク
スポンサーリンク
  1. 業務・実務で使える JavaScript ユーティリティ:数値を整数に丸める方法
  2. 最初に整理する:「整数に丸める」には4種類ある
  3. ステップ1:まずはMath.round()の意味を理解する
    1. 四捨五入をしたいなら Math.round()
    2. 0.5 ちょうどの扱いに注意する
  4. ステップ2:切り捨てと切り上げの違いを理解する
    1. Math.floor() は常に小さい側へ進む
    2. Math.ceil() は常に大きい側へ進む
  5. ステップ3:Math.trunc() は「切り捨て」ではなく「小数部分を捨てる」
  6. ステップ4:文字列入力をそのまま丸めない
    1. まず有限の数値へ変換する
    2. 空文字や空白が 0 になる落とし穴
  7. ステップ5:用途ごとに丸め方を決める
  8. 業務で使える基本テンプレート その1:四捨五入する
  9. 業務で使える基本テンプレート その2:切り捨て・切り上げ・小数切り落とし
  10. 業務で使える完成版テンプレート:丸め方法を明示して共通化する
  11. 初心者が間違えやすいポイントを深掘りする
    1. Math.floor() は「小数点以下を消す」関数ではない
    2. ビット演算で整数化しない
    3. 丸めた後の負の0にも注意する
  12. 金額計算で特に注意したいこと
    1. 小数の計算誤差が丸め結果へ影響することがある
  13. 実務でよくある用途別の例
    1. ページ数を切り上げる
    2. 在庫として使う数量を下へ丸める
    3. 表示用の割合を四捨五入する
  14. テストで正常系と境界条件を確認する
  15. まとめ

業務・実務で使える JavaScript ユーティリティ:数値を整数に丸める方法

JavaScriptで数値を整数に丸めたい場面は、業務でも非常によくあります。請求金額の端数処理、画面のページ番号、在庫数、集計結果の表示、パーセンテージの整数表示、画像サイズの計算結果など、小数のままでは扱いにくい値は多いからです。

ただし、最初に理解しておきたいのは、「整数に丸める」と言っても方法は1つではないということです。四捨五入したいのか、常に切り捨てたいのか、常に切り上げたいのか、0へ近づけたいのかによって、使う関数が変わります。

さらに、負の数の扱い、文字列入力の処理、NaN や Infinity の除外、金額計算での誤差など、初心者が見落としやすい点もあります。この記事では、まず丸め方の違いを整理し、そのうえで実務で再利用しやすい関数を段階的に作っていきます。

最初に整理する:「整数に丸める」には4種類ある

JavaScriptで代表的な整数丸めには、次の4種類があります。

  • Math.round() は四捨五入です。
  • Math.floor() は常に小さい側へ切り捨てます。
  • Math.ceil() は常に大きい側へ切り上げます。
  • Math.trunc() は小数部分を単純に捨てます。

この違いは、正の数では似て見えることがありますが、負の数で特に重要になります。

// 代表的な丸め方の違いを比較する
console.log(Math.round(3.6));  // 4
console.log(Math.floor(3.6));  // 3
console.log(Math.ceil(3.6));   // 4
console.log(Math.trunc(3.6));  // 3

console.log(Math.round(-3.6)); // -4
console.log(Math.floor(-3.6)); // -4
console.log(Math.ceil(-3.6));  // -3
console.log(Math.trunc(-3.6)); // -3
JavaScript

「なんとなく丸める」ではなく、どの方向へ丸めたいのかを先に決めることが重要です。

ステップ1:まずはMath.round()の意味を理解する

四捨五入をしたいなら Math.round()

もっともよく使われるのが Math.round() です。小数部分を見て、最も近い整数へ丸めます。

// 四捨五入の基本例
console.log(Math.round(3.2)); // 3
console.log(Math.round(3.5)); // 4
console.log(Math.round(3.8)); // 4
JavaScript

表示用の件数や、割合をおおまかな整数で見せたい場合などでは、まずこの関数が候補になります。

0.5 ちょうどの扱いに注意する

Math.round() は、ちょうど 0.5 のとき、正の数では上側へ進みます。

// 0.5 は上側の整数へ進む
console.log(Math.round(1.5)); // 2
console.log(Math.round(2.5)); // 3
JavaScript

ただし、負の数では見た目どおりに「絶対値が大きい側」へ進むわけではありません。JavaScriptの Math.round() は、-1.5 を -1 にします。

// 負の 0.5 は注意が必要
console.log(Math.round(-1.5)); // -1
console.log(Math.round(-2.5)); // -2
JavaScript

これは「常に遠い側へ丸める」と思い込むと間違えやすい部分です。負数を扱う業務では、実際の結果を必ず確認します。

ステップ2:切り捨てと切り上げの違いを理解する

Math.floor() は常に小さい側へ進む

Math.floor() は、数直線で見て常に小さい側の整数へ進みます。正の数だけを見ると「小数を捨てる」と思いやすいですが、負の数では結果が変わります。

// floor は常に小さい側へ進む
console.log(Math.floor(3.9));   // 3
console.log(Math.floor(3.1));   // 3
console.log(Math.floor(-3.1));  // -4
console.log(Math.floor(-3.9));  // -4
JavaScript

たとえば、在庫数のように「超えない範囲で下へ丸めたい」処理では使いやすいです。ただし、負数を扱うと絶対値が大きくなる方向へ進むことに注意します。

Math.ceil() は常に大きい側へ進む

Math.ceil() は、数直線で見て常に大きい側の整数へ進みます。

// ceil は常に大きい側へ進む
console.log(Math.ceil(3.1));    // 4
console.log(Math.ceil(3.9));    // 4
console.log(Math.ceil(-3.1));   // -3
console.log(Math.ceil(-3.9));   // -3
JavaScript

必要数を不足なく見積もる計算や、ページ数を切り上げる処理ではよく使います。たとえば、25件のデータを10件ずつ表示する場合、ページ数は Math.ceil(25 / 10) で 3 になります。

ステップ3:Math.trunc() は「切り捨て」ではなく「小数部分を捨てる」

Math.trunc() は、小数部分を単純に取り除きます。これは、正の数では Math.floor() と同じ結果に見えますが、負の数では異なります。

// trunc は小数部分だけを落とす
console.log(Math.trunc(3.9));   // 3
console.log(Math.trunc(3.1));   // 3
console.log(Math.trunc(-3.1));  // -3
console.log(Math.trunc(-3.9));  // -3
JavaScript

つまり、Math.trunc() は「0へ近づける丸め」と考えると理解しやすいです。

たとえば、「金額の小数部は不要なので表示だけ消したい」「符号はそのままにして小数だけ落としたい」といった用途では選択肢になります。ただし、会計上の端数処理ルールとして正しいかは別問題です。

ステップ4:文字列入力をそのまま丸めない

実務では、フォームやCSVから読み込んだ値が文字列になっていることがよくあります。そのため、"12.8" のような値を丸めたくなることがあります。

ただし、丸める前に、まず「安全に数値へ変換できるか」を確認することが大切です。未入力や不正値を、そのまま丸め関数へ渡さないようにします。

まず有限の数値へ変換する

/**
 * 入力値を有限の数値へ変換します。
 *
 * @param {unknown} value 入力値
 * @returns {number | null} 正常なら number、失敗なら null
 */
function toFiniteNumber(value) {
  // すでに数値型なら、そのまま有限数か確認する
  if (typeof value === "number") {
    return Number.isFinite(value) ? value : null;
  }

  // 文字列なら前後の空白を除去してから変換する
  if (typeof value === "string") {
    const trimmed = value.trim();

    // 空文字は未入力として扱う
    if (trimmed === "") {
      return null;
    }

    const converted = Number(trimmed);

    // NaN や Infinity は不正
    return Number.isFinite(converted) ? converted : null;
  }

  // それ以外の型は不正
  return null;
}

console.log(toFiniteNumber("12.8"));   // 12.8
console.log(toFiniteNumber(""));       // null
console.log(toFiniteNumber("abc"));    // null
console.log(toFiniteNumber(Infinity)); // null
JavaScript

このように、変換と丸めを分けておくと、どこで失敗したかがわかりやすくなります。

空文字や空白が 0 になる落とし穴

Number() は、空文字や空白だけの文字列を 0 にしてしまいます。

// Number() の変換には注意が必要
console.log(Number(""));    // 0
console.log(Number("   ")); // 0
JavaScript

未入力を 0 と誤解すると、件数や金額の計算で大きな誤りにつながります。そのため、実務では変換前に空文字を除外する設計が重要です。

ステップ5:用途ごとに丸め方を決める

業務でよくある丸めの用途を整理すると、次のようになります。

  • 表示用の割合や件数なら、四捨五入の Math.round() が向いています。
  • 超えない範囲で抑えたい数量なら、Math.floor() が向いています。
  • 不足しないように必要数を見積もるなら、Math.ceil() が向いています。
  • 小数部分だけ消したいなら、Math.trunc() が候補になります。

丸め方を決めずに関数を1個だけ作ると、用途によって誤用されやすくなります。「何のための丸めか」を関数名で表すと、チーム開発でも読みやすくなります。

業務で使える基本テンプレート その1:四捨五入する

まずは、もっとも基本的な四捨五入の関数です。文字列入力にも対応し、失敗時は null を返します。

/**
 * 値を四捨五入して整数にします。
 *
 * @param {unknown} value 入力値
 * @returns {number | null} 正常なら整数、失敗なら null
 */
function roundToInteger(value) {
  // まず有限数へ変換する
  const number = toFiniteNumber(value);

  // 変換できなければ null
  if (number === null) {
    return null;
  }

  // 四捨五入して返す
  return Math.round(number);
}

console.log(roundToInteger(3.2));     // 3
console.log(roundToInteger(3.5));     // 4
console.log(roundToInteger("12.8"));  // 13
console.log(roundToInteger("abc"));   // null
JavaScript

この関数は、割合や平均値の表示など、「最も近い整数で見せたい」用途に向いています。

業務で使える基本テンプレート その2:切り捨て・切り上げ・小数切り落とし

用途別に関数を分けると、意図が伝わりやすくなります。

/**
 * 値を切り捨てて整数にします。
 *
 * @param {unknown} value 入力値
 * @returns {number | null} 正常なら整数、失敗なら null
 */
function floorToInteger(value) {
  const number = toFiniteNumber(value);

  if (number === null) {
    return null;
  }

  return Math.floor(number);
}

/**
 * 値を切り上げて整数にします。
 *
 * @param {unknown} value 入力値
 * @returns {number | null} 正常なら整数、失敗なら null
 */
function ceilToInteger(value) {
  const number = toFiniteNumber(value);

  if (number === null) {
    return null;
  }

  return Math.ceil(number);
}

/**
 * 値の小数部分を切り落として整数にします。
 *
 * @param {unknown} value 入力値
 * @returns {number | null} 正常なら整数、失敗なら null
 */
function truncToInteger(value) {
  const number = toFiniteNumber(value);

  if (number === null) {
    return null;
  }

  return Math.trunc(number);
}

console.log(floorToInteger(3.9));    // 3
console.log(floorToInteger(-3.1));   // -4

console.log(ceilToInteger(3.1));     // 4
console.log(ceilToInteger(-3.9));    // -3

console.log(truncToInteger(3.9));    // 3
console.log(truncToInteger(-3.9));   // -3
JavaScript

正の数だけを想定していると、floor と trunc の違いを見落としやすいです。負の値がありうる仕様では、必ずテストしてから使います。

業務で使える完成版テンプレート:丸め方法を明示して共通化する

複数の丸め方を1つのユーティリティで扱いたい場合は、丸め方法を引数で明示すると使いやすくなります。

/**
 * 値を指定した方法で整数へ丸めます。
 *
 * mode:
 * - "round" : 四捨五入
 * - "floor" : 常に小さい側へ切り捨て
 * - "ceil"  : 常に大きい側へ切り上げ
 * - "trunc" : 小数部分を切り落とす
 *
 * @param {unknown} value 入力値
 * @param {"round" | "floor" | "ceil" | "trunc"} mode 丸め方法
 * @returns {number | null} 正常なら整数、失敗なら null
 * @throws {TypeError} mode が不正な場合
 */
function toRoundedInteger(value, mode = "round") {
  // まず有限数へ変換する
  const number = toFiniteNumber(value);

  // 数値として使えなければ null
  if (number === null) {
    return null;
  }

  // 丸め方法ごとに処理を分ける
  switch (mode) {
    case "round":
      return Math.round(number);

    case "floor":
      return Math.floor(number);

    case "ceil":
      return Math.ceil(number);

    case "trunc":
      return Math.trunc(number);

    default:
      throw new TypeError("mode は round, floor, ceil, trunc のいずれかで指定してください");
  }
}

console.log(toRoundedInteger("12.6", "round")); // 13
console.log(toRoundedInteger("12.6", "floor")); // 12
console.log(toRoundedInteger("12.1", "ceil"));  // 13
console.log(toRoundedInteger("-12.9", "trunc")); // -12
console.log(toRoundedInteger("abc", "round"));   // null
JavaScript

この関数の利点は、変換ルールが1か所にまとまることです。一方で、呼び出し側の意図が少し見えにくくなる場合もあるため、実際の業務コードでは用途別ラッパー関数を併用すると読みやすくなります。

初心者が間違えやすいポイントを深掘りする

Math.floor() は「小数点以下を消す」関数ではない

正の数だけを見ると、Math.floor() は小数部分を消しているように見えます。しかし、負の数では違います。

// floor は「小さい側」へ進む
console.log(Math.floor(3.9));   // 3
console.log(Math.floor(-3.9));  // -4
JavaScript

「小数点以下を消したい」だけなら、負の数では Math.trunc() のほうがイメージに近いです。関数名だけで判断せず、負数での動きを必ず確認します。

ビット演算で整数化しない

古いコードでは、value | 0 のようなビット演算で整数化する例があります。しかし、これは 32bit 整数へ変換するため、大きな値や意図しない値で問題を起こしやすいです。

// ビット演算による整数化は、32bit 整数の範囲へ変換される
console.log(3.9 | 0);          // 3
console.log(-3.9 | 0);         // -3
console.log(2147483648 | 0);   // -2147483648
JavaScript

見た目は便利でも、実務で安全な丸め処理としてはおすすめしにくいです。可読性の面でも、Math.trunc() などの明示的な関数を使うほうがわかりやすくなります。

丸めた後の負の0にも注意する

JavaScriptには -0 があります。通常の表示では 0 に見えますが、厳密には区別されることがあります。

// 負の 0 が発生する例
const value = Math.round(-0.1);

console.log(value);             // -0
console.log(Object.is(value, -0)); // true
JavaScript

多くの業務では問題になりませんが、表示や比較を厳密に扱う場面では知っておくと役立ちます。必要なら、丸めた後に Object.is(result, -0) ? 0 : result のように正規化します。

金額計算で特に注意したいこと

小数の計算誤差が丸め結果へ影響することがある

JavaScriptの number 型は、2進浮動小数点で表現されます。そのため、一見きれいな小数でも内部では誤差を含むことがあります。

// 小数の内部表現による誤差の例
console.log(0.1 + 0.2); // 0.30000000000000004
JavaScript

この誤差は、丸め結果に影響する場合があります。たとえば、表示上は 1.005 を小数第2位で四捨五入したいのに、期待どおりにならないことがあります。

この記事の主題は「整数へ丸める」ことですが、金額や税計算では「どの単位で」「どの段階で」「どのルールで」丸めるかを業務仕様として明確にすることが大切です。必要なら、整数化の前に計算単位を見直すか、専用ライブラリーの利用も検討します。

実務でよくある用途別の例

ページ数を切り上げる

件数を1ページあたりの表示数で割り、ページ数を不足なく求めるときは Math.ceil() を使います。

/**
 * 総件数と1ページあたりの件数からページ数を計算します。
 *
 * @param {unknown} totalCount 総件数
 * @param {unknown} perPage 1ページあたりの件数
 * @returns {number | null} 正常ならページ数、失敗なら null
 */
function calculatePageCount(totalCount, perPage) {
  const total = toFiniteNumber(totalCount);
  const size = toFiniteNumber(perPage);

  // 数値として不正なら null
  if (total === null || size === null) {
    return null;
  }

  // 0以下のページサイズは不正
  if (size <= 0) {
    return null;
  }

  // 必要ページ数を切り上げで求める
  return Math.ceil(total / size);
}

console.log(calculatePageCount(25, 10)); // 3
console.log(calculatePageCount("21", "5")); // 5
JavaScript

在庫として使う数量を下へ丸める

/**
 * 数量を超えない範囲で整数化します。
 *
 * @param {unknown} value 入力値
 * @returns {number | null} 正常なら整数、失敗なら null
 */
function toStockCount(value) {
  const number = toFiniteNumber(value);

  if (number === null) {
    return null;
  }

  // 在庫として超えないよう、下へ丸める
  return Math.floor(number);
}

console.log(toStockCount(12.9));   // 12
console.log(toStockCount("8.2"));  // 8
JavaScript

表示用の割合を四捨五入する

/**
 * 割合を表示用の整数パーセントへ丸めます。
 *
 * @param {unknown} ratio 0〜1 の割合
 * @returns {number | null} 正常なら整数パーセント、失敗なら null
 */
function toPercentInteger(ratio) {
  const number = toFiniteNumber(ratio);

  if (number === null) {
    return null;
  }

  // 100倍して四捨五入する
  return Math.round(number * 100);
}

console.log(toPercentInteger(0.123));   // 12
console.log(toPercentInteger("0.987")); // 99
JavaScript

このように、単なる丸め関数ではなく、用途を表した関数名にすると、コードを読む側が意図を理解しやすくなります。

テストで正常系と境界条件を確認する

丸め処理は短いコードでも、境界条件が多いです。正の数だけでなく、負の数、0.5 境界、文字列、不正入力を確認します。

// toRoundedInteger() のテスト例
const testCases = [
  [3.2, "round", 3],
  [3.5, "round", 4],
  [3.8, "round", 4],
  [-3.2, "round", -3],
  [-3.5, "round", -3],
  [-3.8, "round", -4],

  [3.9, "floor", 3],
  [-3.1, "floor", -4],

  [3.1, "ceil", 4],
  [-3.9, "ceil", -3],

  [3.9, "trunc", 3],
  [-3.9, "trunc", -3],

  ["12.6", "round", 13],
  ["", "round", null],
  ["   ", "round", null],
  ["abc", "round", null],
  [Infinity, "round", null]
];

// 期待値と実際の値を比較する
for (const [input, mode, expected] of testCases) {
  const actual = toRoundedInteger(input, mode);

  console.log({
    input,
    mode,
    expected,
    actual,
    pass: Object.is(actual, expected)
  });
}
JavaScript

特に負の値については、「直感」と「実際の結果」がズレやすいです。関数を作ったら、負の小数もテストに必ず含めるようにします。

まとめ

JavaScriptで数値を整数に丸めるときは、まず「どの方向へ丸めたいのか」を明確にすることが大切です。四捨五入、切り捨て、切り上げ、小数切り落としは、それぞれ用途が異なります。

  • 四捨五入には Math.round() を使います。
  • 常に小さい側へ進めるなら Math.floor() を使います。
  • 常に大きい側へ進めるなら Math.ceil() を使います。
  • 小数部分だけ落としたいなら Math.trunc() を使います。
  • 文字列入力は、空文字を除外してから数値変換します。
  • 負の数では結果が変わりやすいため、必ずテストします。
  • 金額計算では、浮動小数点誤差と丸めルールを業務仕様として確認します。

実務で本当に重要なのは、単に整数にすることではなく、「どのルールで丸めた整数だけを業務処理へ渡すか」を明確にすることです。入力変換、丸め方法、用途別ルールを分けて設計することで、保守しやすく、安心して再利用できるコードになります。

タイトルとURLをコピーしました