JavaScript Tips | 数値・計算:整数かどうか判定する

JavaScript JavaScript
スポンサーリンク
スポンサーリンク
  1. 業務・実務で使える JavaScript ユーティリティ:整数かどうか判定する方法
  2. 最初に整理する:「整数かどうか」は1つの意味ではない
  3. ステップ1:まずは整数の数値型かどうか判定する
    1. Number.isInteger() が基本になる
    2. 10.0 は整数として扱われる
  4. ステップ2:typeof だけでは足りない理由を理解する
  5. ステップ3:文字列として受け取る整数入力を考える
    1. Number() で変換してから Number.isInteger() で判定する
    2. 空文字や空白だけを先に除外する理由
  6. ステップ4:parseInt() を判定の中心にしない
  7. ステップ5:業務ルールをあとから重ねる
  8. 業務で使える基本テンプレート その1:整数の数値型か判定する
  9. 業務で使える基本テンプレート その2:整数として読める文字列か判定する
    1. 「見た目としても整数表記だけを許可したい」場合
  10. 業務で使える完成版テンプレート:整数へ安全に変換する
  11. 初心者が迷いやすいポイントを深掘りする
    1. 10.0 を許可するかは「数値」と「入力文字列」で分けて考える
    2. 指数表記を許可するか確認する
    3. 安全な整数かどうかも必要になることがある
    4. 全角数字はそのままでは通らない
  12. 実務でよくある用途別の判定例
    1. ページ番号:1以上の整数
    2. 在庫数:0以上の整数
    3. 年齢:0以上150以下の整数
  13. テストで正常系と境界条件を確認する
  14. まとめ

業務・実務で使える JavaScript ユーティリティ:整数かどうか判定する方法

JavaScriptで「整数かどうか」を判定したい場面は、業務でも非常によくあります。ページ番号、在庫数、件数、年齢、ランク、並び順、CSVの行番号、APIのIDなど、小数を許可しない値は多いからです。

ただし、最初に理解しておきたいのは、「整数かどうか」の判定にも段階があるということです。たとえば、10 のような数値型だけを対象にしたいのか、"10" のような文字列も「整数として読める入力」として受け付けたいのかで、実装は変わります。

さらに、NaN、Infinity、空文字、空白、"10.0" の扱い、負の整数を許可するかどうかなど、初心者が迷いやすい点もあります。この記事では、まず「何を整数として扱うか」を整理し、そのうえで実務で再利用しやすい関数を段階的に作っていきます。

最初に整理する:「整数かどうか」は1つの意味ではない

実務では、「整数かどうか」という質問の中に、実は複数の条件が含まれています。まずは次の3つを分けて考えると整理しやすくなります。

  • JavaScriptの値として、すでに整数の数値型であるか。
  • 文字列だが、整数として読み取れる入力か。
  • 0以上、1以上、範囲内など、業務ルールを満たす整数か。

たとえば、10 は整数の数値型です。"10" は数値型ではありませんが、整数として読める文字列です。さらに -10 は整数ですが、「在庫数は0以上」という業務ルールには合いません。

つまり、型の判定、文字列からの変換、業務条件のチェックを混同しないことが重要です。

ステップ1:まずは整数の数値型かどうか判定する

Number.isInteger() が基本になる

JavaScriptで、値が整数の数値型かどうかを最も素直に判定できるのが Number.isInteger() です。

// 整数の数値型だけを true にする
console.log(Number.isInteger(10));      // true
console.log(Number.isInteger(0));       // true
console.log(Number.isInteger(-5));      // true

console.log(Number.isInteger(3.14));    // false
console.log(Number.isInteger("10"));    // false
console.log(Number.isInteger(NaN));     // false
console.log(Number.isInteger(Infinity)); // false
JavaScript

この関数の良いところは、文字列を勝手に数値として扱わないことです。"10" は見た目が整数でも文字列なので、false になります。型の厳密さを保ちたい業務コードでは、この挙動がわかりやすくなります。

10.0 は整数として扱われる

初心者が混乱しやすい点の1つに、10.0 の扱いがあります。見た目は小数のようですが、JavaScriptの数値としては整数値と同じです。

// 値として小数部分が 0 なら整数扱いになる
console.log(Number.isInteger(10.0)); // true
console.log(Number.isInteger(10.00)); // true
JavaScript

これは「小数点を書いたかどうか」ではなく、「値として整数かどうか」で判定しているからです。画面上の書式と、内部の数値判定は別物として考える必要があります。

ステップ2:typeof だけでは足りない理由を理解する

typeof value === "number" で数値型かどうかは確認できますが、それだけでは整数かどうかはわかりません。

// 数値型かどうかだけでは、整数か小数かを区別できない
console.log(typeof 10);    // "number"
console.log(typeof 3.14);  // "number"
console.log(typeof NaN);   // "number"
JavaScript

さらに、NaN や Infinity も number 型です。そのため、typeof は型の大まかな確認には使えても、「業務で使える整数か」という判定には不十分です。

整数判定の中心は、Number.isInteger() を使うと覚えると整理しやすくなります。

ステップ3:文字列として受け取る整数入力を考える

フォーム入力やCSVでは、値が文字列として渡されることが多いです。そのため、"10" や "-5" を「整数として読める入力」として扱いたい場面があります。

この場合に大切なのは、文字列そのものを整数とみなすのではなく、安全に整数へ変換できるかを確認するという考え方です。

Number() で変換してから Number.isInteger() で判定する

// 文字列を整数として読めるか確認する関数
function isIntegerString(value) {
  // 文字列以外は受け付けない
  if (typeof value !== "string") {
    return false;
  }

  // 前後の空白を除去する
  const trimmed = value.trim();

  // 空文字は不正にする
  if (trimmed === "") {
    return false;
  }

  // 数値へ変換する
  const converted = Number(trimmed);

  // 変換後の値が整数なら true
  return Number.isInteger(converted);
}

console.log(isIntegerString("10"));     // true
console.log(isIntegerString("-5"));     // true
console.log(isIntegerString("3.14"));   // false
console.log(isIntegerString("abc"));    // false
console.log(isIntegerString(""));       // false
JavaScript

この形なら、空文字や数値以外の文字列を自然に除外できます。

空文字や空白だけを先に除外する理由

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

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

未入力を 0 と見なしてしまうと、ページ番号、件数、年齢、在庫数などで誤判定が起こります。フォーム入力の検証では、変換より前に空文字チェックを入れることが重要です。

ステップ4:parseInt() を判定の中心にしない

整数判定で初心者がよく使うのが parseInt() ですが、これは「先頭から読める整数部分を取り出す」関数です。そのため、厳密な入力検証には向かない場合があります。

// 途中まで読めれば整数として返してしまう
console.log(parseInt("10abc", 10));   // 10
console.log(parseInt("3.14", 10));    // 3
console.log(parseInt("08", 10));      // 8
JavaScript

たとえば、件数入力で "10abc" を不正にしたいなら、parseInt() の結果だけを見てはいけません。3.14 を整数として不正にしたい場合も、parseInt("3.14", 10) は 3 を返してしまいます。

「整数として正しい入力か」を見たいなら、まずは Number() と Number.isInteger() を中心に考えるほうが安全です。

ステップ5:業務ルールをあとから重ねる

整数判定の実務では、「整数なら何でもよい」ことは少なく、次のような条件が追加されることが多いです。

  • 0以上の整数だけを許可する。
  • 1以上の整数だけを許可する。
  • 最大値を超えないようにする。
  • 安全な整数だけを許可する。

つまり、まず「整数へ安全に変換できるか」を確認し、そのあとで用途別ルールを重ねる設計にすると、再利用しやすくなります。

業務で使える基本テンプレート その1:整数の数値型か判定する

まずは、すでにJavaScriptの値として存在しているものが、整数の数値型かどうかを判定する関数です。

/**
 * 値が整数の数値型かを判定します。
 *
 * @param {unknown} value 判定対象
 * @returns {boolean} 整数の数値型なら true
 */
function isIntegerNumber(value) {
  // Number.isInteger() は数値型の整数だけを true にする
  return Number.isInteger(value);
}

console.log(isIntegerNumber(10));        // true
console.log(isIntegerNumber(-3));        // true
console.log(isIntegerNumber(3.14));      // false
console.log(isIntegerNumber("10"));      // false
console.log(isIntegerNumber(NaN));       // false
console.log(isIntegerNumber(Infinity));  // false
JavaScript

この関数は、APIの内部処理や、すでに変換済みの値に対するチェックで使いやすいです。

業務で使える基本テンプレート その2:整数として読める文字列か判定する

次に、フォーム入力やCSVなどで受け取る文字列を対象にした関数です。

/**
 * 値が「整数として読める文字列」かを判定します。
 *
 * 仕様:
 * - 文字列だけを受け付けます。
 * - 前後の空白は無視します。
 * - 空文字は不正です。
 * - Number() で変換後、整数なら true にします。
 *
 * @param {unknown} value 判定対象
 * @returns {boolean} 整数字符列なら true
 */
function isIntegerString(value) {
  // 文字列以外は不正
  if (typeof value !== "string") {
    return false;
  }

  // 前後の空白を除去する
  const trimmed = value.trim();

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

  // 数値へ変換する
  const converted = Number(trimmed);

  // 整数として使えるなら true
  return Number.isInteger(converted);
}

console.log(isIntegerString("10"));     // true
console.log(isIntegerString(" 10 "));   // true
console.log(isIntegerString("-5"));     // true
console.log(isIntegerString("3.14"));   // false
console.log(isIntegerString("abc"));    // false
console.log(isIntegerString(""));       // false
JavaScript

この関数では、"10.0" は Number("10.0") が 10 になるため、整数として true になります。これを許可するかどうかは仕様次第です。

「見た目としても整数表記だけを許可したい」場合

もし "10.0" や "001" の扱いまで厳密に決めたいなら、文字列表記のルールを別に定義する必要があります。たとえば「マイナス記号と数字だけ」「小数点は不可」といった制約です。

/**
 * 見た目としても整数表記だけを許可します。
 *
 * 仕様:
 * - 前後の空白は無視します。
 * - 符号付き整数表記だけを許可します。
 * - 小数点、指数表記、カンマ区切りは不可です。
 *
 * @param {unknown} value 判定対象
 * @returns {boolean} 整数表記なら true
 */
function isStrictIntegerString(value) {
  // 文字列以外は不正
  if (typeof value !== "string") {
    return false;
  }

  const trimmed = value.trim();

  // 空文字は不正
  if (trimmed === "") {
    return false;
  }

  // 符号付き整数表記だけを許可する
  return /^[+-]?\d+$/.test(trimmed);
}

console.log(isStrictIntegerString("10"));    // true
console.log(isStrictIntegerString("-5"));    // true
console.log(isStrictIntegerString("10.0"));  // false
console.log(isStrictIntegerString("1e3"));   // false
console.log(isStrictIntegerString("1,000")); // false
JavaScript

この関数は「文字列表記として整数らしいか」を判定するものです。数値変換そのものとは目的が異なるため、関数を分けておくと意図が伝わりやすくなります。

業務で使える完成版テンプレート:整数へ安全に変換する

実務では、最終的にほしいのは true / false だけでなく、「使える整数なら number で受け取りたい」ということが多いです。そこで、変換と検証をまとめた関数を用意します。

/**
 * 入力値を安全に整数へ変換します。
 *
 * 仕様:
 * - 数値型は、そのまま整数か確認します。
 * - 文字列は trim() 後に Number() で変換します。
 * - 空文字、空白だけ、NaN、Infinity は不正です。
 * - 整数でない場合も不正です。
 * - 変換できたら number を返し、失敗したら null を返します。
 *
 * @param {unknown} value 入力値
 * @returns {number | null} 正常な整数なら number、失敗なら null
 */
function toInteger(value) {
  // すでに数値型なら整数か確認する
  if (typeof value === "number") {
    return Number.isInteger(value) ? value : null;
  }

  // 文字列なら前処理してから変換する
  if (typeof value === "string") {
    const trimmed = value.trim();

    // 空文字は不正
    if (trimmed === "") {
      return null;
    }

    const converted = Number(trimmed);

    // 整数なら返し、そうでなければ null
    return Number.isInteger(converted) ? converted : null;
  }

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

/**
 * 値が整数として利用できるか判定します。
 *
 * @param {unknown} value 入力値
 * @returns {boolean} 利用可能な整数なら true
 */
function isUsableInteger(value) {
  return toInteger(value) !== null;
}

/**
 * 値が0以上の整数として利用できるか判定します。
 *
 * @param {unknown} value 入力値
 * @returns {boolean} 0以上の整数なら true
 */
function isNonNegativeInteger(value) {
  const integer = toInteger(value);

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

  return integer >= 0;
}

// 利用例
console.log(toInteger("10"));       // 10
console.log(toInteger(" 10 "));     // 10
console.log(toInteger("-5"));       // -5
console.log(toInteger("10.0"));     // 10
console.log(toInteger("3.14"));     // null
console.log(toInteger("abc"));      // null
console.log(toInteger(""));         // null
console.log(toInteger(Infinity));   // null

console.log(isUsableInteger("10"));       // true
console.log(isUsableInteger("3.14"));     // false

console.log(isNonNegativeInteger("0"));   // true
console.log(isNonNegativeInteger("-1"));  // false
JavaScript

この設計の利点は、整数への変換ルールが1か所に集まることです。将来、「指数表記は許可しない」「全角数字を事前変換する」といった仕様変更があっても、中心となる関数を見直しやすくなります。

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

10.0 を許可するかは「数値」と「入力文字列」で分けて考える

Number.isInteger(10.0) は true です。これは値としては 10 と同じだからです。

// 値としては整数なので true
console.log(Number.isInteger(10.0)); // true
JavaScript

一方で、フォーム入力として "10.0" を受け取った場合、それを「整数入力」とみなすかどうかは仕様次第です。数値変換後の値だけを重視するなら許可できますし、見た目としても整数表記だけを許可したいなら、正規表現などで別ルールを設けます。

指数表記を許可するか確認する

Number("1e3") は 1000 です。そのため、変換後に Number.isInteger() を使う関数では、指数表記も整数として通ります。

// 指数表記は数値変換すると整数になる
console.log(Number("1e3"));               // 1000
console.log(Number.isInteger(Number("1e3"))); // true
JavaScript

業務入力として指数表記を受け付けたくない場合は、isStrictIntegerString() のような表記ルールの関数を使うほうが明確です。

安全な整数かどうかも必要になることがある

JavaScriptの number 型は、非常に大きな整数を正確に表せないことがあります。たとえばIDや件数のように大きな整数を扱う場合は、Number.isSafeInteger() を使う選択肢もあります。

// 安全に表現できる整数かどうかを判定する
console.log(Number.isSafeInteger(123)); // true
console.log(Number.isSafeInteger(9007199254740991)); // true
console.log(Number.isSafeInteger(9007199254740992)); // false
JavaScript

通常の在庫数やページ番号では、ここまで気にしなくてよいことが多いです。ただし、長い数値IDや大量データの件数などでは、単なる整数判定だけで十分かを確認します。

全角数字はそのままでは通らない

日本語入力では、"123" のような全角数字が入ることがあります。これはそのままでは通常の数値変換に失敗します。

// 全角数字はそのままでは整数として扱えない
console.log(Number("123")); // NaN
JavaScript

これを許可したい場合は、事前に半角へ正規化する処理を別で用意します。ただし、全角マイナス、全角プラス、小数点なども含めると仕様が広がるため、入力UI側で制御するほうが簡単な場合もあります。

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

ページ番号:1以上の整数

/**
 * ページ番号として妥当か判定します。
 *
 * @param {unknown} value 入力値
 * @returns {boolean} 1以上の整数なら true
 */
function isPageNumber(value) {
  const integer = toInteger(value);

  if (integer === null) {
    return false;
  }

  return integer >= 1;
}

console.log(isPageNumber("1"));   // true
console.log(isPageNumber("0"));   // false
console.log(isPageNumber("1.5")); // false
JavaScript

在庫数:0以上の整数

/**
 * 在庫数として妥当か判定します。
 *
 * @param {unknown} value 入力値
 * @returns {boolean} 0以上の整数なら true
 */
function isStockCount(value) {
  return isNonNegativeInteger(value);
}

console.log(isStockCount("0"));    // true
console.log(isStockCount("10"));   // true
console.log(isStockCount("-1"));   // false
console.log(isStockCount("2.5"));  // false
JavaScript

年齢:0以上150以下の整数

/**
 * 年齢として妥当か判定します。
 *
 * @param {unknown} value 入力値
 * @returns {boolean} 0以上150以下の整数なら true
 */
function isAge(value) {
  const integer = toInteger(value);

  if (integer === null) {
    return false;
  }

  return integer >= 0 && integer <= 150;
}

console.log(isAge("20"));   // true
console.log(isAge("-1"));   // false
console.log(isAge("151"));  // false
JavaScript

このように、基礎となる変換関数を1つ用意しておくと、用途別の判定関数を短く、読みやすく作れます。

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

整数判定の関数は短く見えても、境界条件が多いです。通常の整数だけでなく、小数、空文字、空白、NaN、Infinity、指数表記、文字混在なども確認します。

// toInteger() のテスト例
const testCases = [
  [10, 10],
  [-5, -5],
  [0, 0],
  [10.0, 10],
  [3.14, null],
  [NaN, null],
  [Infinity, null],
  [-Infinity, null],
  ["10", 10],
  [" 10 ", 10],
  ["-5", -5],
  ["10.0", 10],
  ["1e3", 1000],
  ["3.14", null],
  ["", null],
  ["   ", null],
  ["abc", null],
  ["10abc", null],
  [null, null],
  [undefined, null],
  [true, null],
  ["123", null]
];

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

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

また、見た目の表記を厳密にしたい場合は、文字列表記ルール用の関数も別にテストします。

// isStrictIntegerString() のテスト例
const strictCases = [
  ["10", true],
  ["-5", true],
  ["+8", true],
  [" 10 ", true],
  ["10.0", false],
  ["1e3", false],
  ["1,000", false],
  ["", false],
  ["abc", false]
];

for (const [input, expected] of strictCases) {
  const actual = isStrictIntegerString(input);

  console.log({
    input,
    expected,
    actual,
    pass: actual === expected
  });
}
JavaScript

このように、変換ルールと表記ルールを分けてテストすると、仕様変更にも対応しやすくなります。

まとめ

JavaScriptで整数かどうか判定するときは、まず「数値型の整数を見たいのか」「文字列入力を整数として受け付けたいのか」を分けて考えることが大切です。そのうえで、用途別の業務条件を追加していきます。

  • すでに数値型かどうかを見るなら、Number.isInteger() が基本です。
  • 文字列入力を扱うなら、空文字を除外してから Number() と Number.isInteger() を組み合わせます。
  • parseInt() は部分一致を許すため、厳密な入力検証の中心には向きません。
  • "10.0" や "1e3" を許可するかは、値としての整数判定と、文字列表記のルールを分けて決めます。
  • 0以上、1以上、範囲内、安全な整数などの業務ルールは別レイヤーで確認します。
  • 基礎となる変換関数を用意すると、ページ番号や在庫数などへ再利用しやすくなります。

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

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