JavaScript/Number/isInteger

カテゴリ:Book:JavaScript#Number/isInteger%20

Number.isInteger() は、ECMAScript における Number オブジェクトのメソッドで、与えられた値が整数であるかどうかを判定します。このメソッドは、値が Number 型であり、小数部を持たない場合に true を返します。

構文

Number.isInteger(value)

パラメータ

value
整数かどうかを判定する値。

戻り値

指定された値が Number 型で整数値である場合は true、そうでない場合は false を返します。

説明

Number.isInteger() メソッドは、引数が以下の条件をすべて満たす場合に true を返します:

  • 引数が Number 型である
  • 引数が有限である(InfinityNaN ではない)
  • 引数が小数部を持たない(Math.floor(value) === value

これらの条件のいずれかに該当しない場合、メソッドは false を返します。

Number.isInteger() は厳密な型チェックを行い、引数を数値に変換しません。そのため、文字列や他のプリミティブ型が渡された場合は false を返します。

特性

Number.isInteger() には、以下のような特性があります:

  • 静的メソッド: このメソッドは Number オブジェクトのプロトタイプではなく、Number コンストラクタに直接関連付けられています。
  • ECMAScript 6: このメソッドは ECMAScript 6(ES2015)で導入されました。
  • 型変換なし: このメソッドは引数を数値に変換せず、引数が Number 型でない場合は常に false を返します。

基本的な使用法

以下のプログラムは、Number.isInteger() の基本的な使用法を示しています。

// 整数値の確認
console.log(Number.isInteger(0)); // true
console.log(Number.isInteger(1)); // true
console.log(Number.isInteger(-100000)); // true

// 浮動小数点数の確認
console.log(Number.isInteger(0.1)); // false
console.log(Number.isInteger(Math.PI)); // false

// 整数として表現される浮動小数点数
console.log(Number.isInteger(1.0)); // true

// 特殊な値
console.log(Number.isInteger(NaN)); // false
console.log(Number.isInteger(Infinity)); // false
console.log(Number.isInteger(-Infinity)); // false
console.log(Number.isInteger(null)); // false
console.log(Number.isInteger(undefined)); // false

// 文字列や他の型
console.log(Number.isInteger("10")); // false
console.log(Number.isInteger(true)); // false
console.log(Number.isInteger({})); // false

このプログラムでは、様々な値に対して Number.isInteger() メソッドを適用し、それらが整数かどうかを確認しています。注目すべき点として、1.0 のような小数点を持つ値でも、実際に整数値として表現される場合は true を返します。

浮動小数点精度の問題

浮動小数点数の精度の問題により、実際には整数であるはずの計算結果が小数部を持つことがあります。以下は、その例です。

// 浮動小数点の精度問題
console.log(0.1 + 0.2); // 0.30000000000000004
console.log(Number.isInteger(0.1 + 0.2)); // false

// 四則演算の結果
let result = 10;
result = result / 3; // 3.3333333333333335
console.log(Number.isInteger(result)); // false

result = result * 3; // 10.000000000000002
console.log(result); // 10.000000000000002
console.log(Number.isInteger(result)); // false

// 微小な誤差の影響
result = Math.pow(2, 53) + 1 - Math.pow(2, 53);
console.log(result); // 0
console.log(Number.isInteger(result)); // true(期待値は 1 だが、精度の問題で 0 になる)

このプログラムでは、浮動小数点数の精度の問題により、整数であるはずの値が小数部を持つことや、逆に整数でないはずの値が整数として扱われることがあることを示しています。この問題は特に大きな数値や複雑な計算を行う場合に顕著になります。

独自の isInteger 実装

Number.isInteger() メソッドが利用できない環境でも、同等の機能を実装できます。

// 独自の isInteger 実装
function isInteger(value) {
  return typeof value === 'number' && 
         isFinite(value) && 
         Math.floor(value) === value;
}

// または ES6 未対応環境での polyfill
if (!Number.isInteger) {
  Number.isInteger = function(value) {
    return typeof value === 'number' && 
           isFinite(value) && 
           Math.floor(value) === value;
  };
}

// テスト
console.log(isInteger(42)); // true
console.log(isInteger(42.5)); // false
console.log(isInteger("42")); // false

このプログラムでは、Number.isInteger() メソッドの独自実装と、古いブラウザ向けの polyfill の例を示しています。この実装は、ECMAScript 仕様に基づいており、公式の実装と同様の動作をします。

実用的な例

配列のインデックス検証

以下のプログラムは、配列のインデックスとして使用される値が有効かどうかを検証する例を示しています。

// 配列のインデックスとして有効かどうかを検証する関数
function isValidArrayIndex(index, array) {
  // 整数かどうか確認
  if (!Number.isInteger(index)) {
    return false;
  }
  
  // 範囲内かどうか確認
  return index >= 0 && index < array.length;
}

// 使用例
const arr = ['a', 'b', 'c', 'd'];

console.log(isValidArrayIndex(2, arr)); // true
console.log(isValidArrayIndex(4, arr)); // false(範囲外)
console.log(isValidArrayIndex(-1, arr)); // false(負の値)
console.log(isValidArrayIndex(2.5, arr)); // false(整数でない)
console.log(isValidArrayIndex('2', arr)); // false(数値型でない)

このプログラムでは、配列のインデックスとして使用される値が整数であり、かつ配列の有効な範囲内にあるかどうかを検証する関数の例を示しています。

パラメータのバリデーション

以下のプログラムは、関数のパラメータが特定の型や条件を満たしているかを検証する例を示しています。

// パラメータの型と条件を検証するクラス
class ParameterValidator {
  // 整数かどうか検証
  static validateInteger(value, paramName) {
    if (!Number.isInteger(value)) {
      throw new TypeError(<code>${paramName} must be an integer</code>);
    }
    return value;
  }
  
  // 正の整数かどうか検証
  static validatePositiveInteger(value, paramName) {
    this.validateInteger(value, paramName);
    if (value <= 0) {
      throw new RangeError(<code>${paramName} must be a positive integer</code>);
    }
    return value;
  }
  
  // 範囲内の整数かどうか検証
  static validateIntegerInRange(value, paramName, min, max) {
    this.validateInteger(value, paramName);
    if (value < min || value > max) {
      throw new RangeError(<code>${paramName} must be an integer between ${min} and ${max}</code>);
    }
    return value;
  }
}

// 使用例
function createPagination(page, pageSize, totalItems) {
  try {
    // パラメータの検証
    const validPage = ParameterValidator.validatePositiveInteger(page, 'page');
    const validPageSize = ParameterValidator.validateIntegerInRange(pageSize, 'pageSize', 1, 100);
    const validTotalItems = ParameterValidator.validateInteger(totalItems, 'totalItems');
    
    // ページネーションの計算
    const totalPages = Math.ceil(validTotalItems / validPageSize);
    
    return {
      currentPage: validPage,
      pageSize: validPageSize,
      totalItems: validTotalItems,
      totalPages: totalPages,
      hasNextPage: validPage < totalPages,
      hasPrevPage: validPage > 1
    };
  } catch (e) {
    console.error(<code>Pagination error: ${e.message}</code>);
    return null;
  }
}

// 正常な使用
console.log(createPagination(2, 10, 95));

// エラーケース
console.log(createPagination(2.5, 10, 95)); // "page must be an integer"
console.log(createPagination(0, 10, 95)); // "page must be a positive integer"
console.log(createPagination(2, 150, 95)); // "pageSize must be an integer between 1 and 100"

このプログラムでは、関数のパラメータが特定の条件(整数、正の整数、範囲内の整数など)を満たしているかを検証するユーティリティクラスの例を示しています。Number.isInteger() メソッドを使用して、値が整数であることを確認しています。

数値の丸め処理

以下のプログラムは、数値を整数に丸める方法と、その結果が整数かどうかを確認する例を示しています。

// 異なる丸め方法と整数チェック
function roundingExample(value) {
  console.log(<code>元の値: ${value}</code>);
  
  // Math.floor: 小数点以下を切り捨て
  const floorResult = Math.floor(value);
  console.log(<code>Math.floor: ${floorResult} (整数: ${Number.isInteger(floorResult)})</code>);
  
  // Math.ceil: 小数点以下を切り上げ
  const ceilResult = Math.ceil(value);
  console.log(<code>Math.ceil: ${ceilResult} (整数: ${Number.isInteger(ceilResult)})</code>);
  
  // Math.round: 四捨五入
  const roundResult = Math.round(value);
  console.log(<code>Math.round: ${roundResult} (整数: ${Number.isInteger(roundResult)})</code>);
  
  // 小数点以下の桁数を指定して丸める
  const toFixedResult = Number(value.toFixed(2));
  console.log(<code>toFixed(2): ${toFixedResult} (整数: ${Number.isInteger(toFixedResult)})</code>);
  
  console.log('---');
}

// 様々な値での実験
roundingExample(3.14159);
roundingExample(-2.7);
roundingExample(5);
roundingExample(0.499);
roundingExample(0.5);

このプログラムでは、様々な丸め方法(Math.floorMath.ceilMath.roundtoFixed)を使用して数値を変換し、その結果が Number.isInteger() メソッドによって整数として認識されるかどうかを確認しています。

浮動小数点数の整数表現

JavaScript では、すべての数値は IEEE 754 倍精度浮動小数点形式で表現されますが、Number.isInteger() メソッドは小数部がない値を整数として判定します。

// 浮動小数点数と整数の関係
console.log(Number.isInteger(1)); // true
console.log(Number.isInteger(1.0)); // true
console.log(Number.isInteger(1.00000000000000)); // true

// 内部表現の確認
console.log(1 === 1.0); // true

// 精度の問題
console.log(Number.isInteger(1.0000000000000001)); // false
console.log(Number.isInteger(1.0000000000000002)); // true(IEEE 754 の精度制限により 1 として表現される)

// 大きな値での精度の問題
const bigInt = Math.pow(2, 52);
console.log(bigInt); // 4503599627370496
console.log(Number.isInteger(bigInt)); // true
console.log(Number.isInteger(bigInt + 0.1)); // true(この大きさでは 0.1 の差は表現できない)
console.log(Number.isInteger(bigInt + 0.5)); // true(同様の理由)
console.log(Number.isInteger(bigInt + 1)); // true(1 の差は表現できる)
console.log(Number.isInteger(bigInt + 1.5)); // false(1.5 の差は表現できる)

このプログラムでは、JavaScript における浮動小数点数の整数表現と精度の問題を示しています。特に大きな値になると、小さな小数部が表現できなくなり、Number.isInteger()true を返す場合があります。

Number.isInteger と Number.isSafeInteger の違い

Number.isInteger()Number.isSafeInteger() の主な違いは以下の通りです:

  • Number.isInteger() は値が整数かどうかのみを判定します。
  • Number.isSafeInteger() は値が整数であり、かつ安全な範囲( から まで)内にあるかどうかを判定します。
// Number.isInteger と Number.isSafeInteger の比較
console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991

// 安全な整数の範囲内
console.log(Number.isInteger(42)); // true
console.log(Number.isSafeInteger(42)); // true

// 安全な整数の範囲を超える値
const unsafe = Math.pow(2, 53); // 9007199254740992
console.log(Number.isInteger(unsafe)); // true(整数として表現されている)
console.log(Number.isSafeInteger(unsafe)); // false(安全な範囲を超えている)

// 安全でない整数の問題
console.log(unsafe); // 9007199254740992
console.log(unsafe + 1); // 9007199254740992(!)期待される値は 9007199254740993
console.log(unsafe === unsafe + 1); // true(精度の問題)

このプログラムでは、Number.isInteger()Number.isSafeInteger() の違いを示しています。大きな整数値の場合、Number.isInteger()true を返しても、その値が正確に表現できるとは限りません。一方、Number.isSafeInteger() は正確に表現および比較できる整数かどうかを判定します。

ブラウザの互換性

Number.isInteger() メソッドは、ECMAScript 6(ES2015)で導入されたため、以下のようなモダンブラウザで利用できます:

  • Chrome 34 以降
  • Firefox 16 以降
  • Safari 9 以降
  • Edge 12 以降
  • Internet Explorer: サポートなし

古いブラウザでこのメソッドを使用する場合は、前述の polyfill を使用することができます。

関連項目

  • Number.isSafeInteger(): 値が安全な整数かどうかを判定するメソッド
  • Number.MAX_SAFE_INTEGER: JavaScript で安全に表現できる最大の整数値を表すプロパティ
  • Number.MIN_SAFE_INTEGER: JavaScript で安全に表現できる最小の整数値を表すプロパティ
  • Math.floor(): 引数以下の最大の整数を返すメソッド
  • Math.ceil(): 引数以上の最小の整数を返すメソッド
  • Math.round(): 引数の値を最も近い整数に丸めるメソッド
  • parseInt(): 文字列を整数に解析するグローバル関数

脚註

    外部リンク

    カテゴリ:Book:JavaScript#Number/isInteger%20 カテゴリ:JavaScript
    カテゴリ:Book:JavaScript カテゴリ:JavaScript カテゴリ:Pages using the JsonConfig extension