JavaScript | 基礎構文:数値・演算 – NaN

JavaScript JavaScript
スポンサーリンク

NaNとは何か

NaNは「Not a Number(数値ではない)」の略で、数値計算の結果が「有効な数」にならなかったときに使われる特別な値です。エラーを投げるのではなく、計算の結果としてNaNが返ります。例えば文字列と数値を不適切に掛け算したり、数値に変換できない文字列を数値化しようとするとNaNになります。

"foo" * 2;      // NaN
Number("abc");  // NaN
JavaScript

NaNが発生する典型例

数値化できない文字列の計算

数値に見えない文字列を数値演算にかけると、数値に変換できずNaNになります。

"hello" - 1;    // NaN
parseFloat("x1"); // NaN
JavaScript

不定形の演算

0で0を割る、無限大から無限大を引くなど「数学的に定まらない」演算はNaNになります。

0 / 0;                // NaN
Infinity - Infinity;  // NaN
JavaScript

数値関数への不正な入力

数学関数に不正なドメインの値を渡すとNaNになります。

Math.sqrt(-1);  // NaN(実数の平方根では定義外)
Math.log(-5);   // NaN(実数の自然対数では定義外)
JavaScript

NaNのふるまい(特徴的なポイント)

自分自身とすら等しくない

NaNはどの値とも等しくないだけでなく、NaN同士でも等しくありません。

NaN === NaN;      // false
Object.is(NaN, NaN); // true(厳密な同一性チェックでは同じとみなせる)
JavaScript

等価演算子では判定できないため、NaNかどうかは専用の関数で確認します。

計算に混ざるとNaNが伝播しやすい

NaNを含む演算は、結果もNaNになりがちです。データ処理の途中でNaNが紛れ込むと、以降の集計がすべてNaNになることがあります。

const x = NaN;
x + 1;    // NaN
x * 2;    // NaN
JavaScript

NaNを判定する正しい方法

Number.isNaNで厳密に判定する

Number.isNaNは「本当にNaNかどうか」を判定します。文字列や未定義値はNaNではありません。

Number.isNaN(NaN);        // true
Number.isNaN("foo");      // false
Number.isNaN(undefined);  // false
JavaScript

isNaNとの違いに注意

グローバルのisNaNは、まず数値へ変換してからNaN判定をするため、意図しないtrueになることがあります。

isNaN("foo");     // true(数値に変換できないから)
Number.isNaN("foo"); // false(値そのものはNaNではない)
JavaScript

基本的にはNumber.isNaNを使うほうが安全です。

Object.isで同一性を確認する

等価演算子ではNaN同士が等しくないため、同一性をどうしても比較したい場合はObject.isを使います。

Object.is(NaN, NaN); // true
JavaScript

NaNを避ける・扱うコツ

入力を先に検証してから計算する

文字列入力は数値へ変換できるか確認してから計算します。NumberやparseFloatで変換し、NaNなら別の処理に切り替えます。

function toNumberSafe(s) {
  const n = Number(s);
  return Number.isNaN(n) ? null : n;
}

const v = toNumberSafe("123"); // 123
const w = toNumberSafe("abc"); // null(変換失敗)
JavaScript

NaNを無効値として扱い、デフォルト値を与える

計算前にNaNならデフォルト値に置き換えます。

const n = Number("abc");
const safe = Number.isNaN(n) ? 0 : n; // 0をデフォルトに
JavaScript

あるいは、null合体演算子や条件分岐で回避します(NaNはnull合体の対象ではないため、判定は必要です)。

集計や平均を取る前にNaNを除外する

配列処理ではNaNをフィルタしてから集計します。

const values = [10, NaN, 20, Number("x")]; // [10, NaN, 20, NaN]
const cleaned = values.filter(v => !Number.isNaN(v));
const avg = cleaned.reduce((s, x) => s + x, 0) / cleaned.length; // 15
JavaScript

例題で理解するNaN

例題1:文字列入力の安全な加算

ユーザー入力を足し算する前に、NaNをチェックして安全に計算します。

function addInputs(aStr, bStr) {
  const a = Number(aStr);
  const b = Number(bStr);
  if (Number.isNaN(a) || Number.isNaN(b)) {
    return "入力が数値ではありません";
  }
  return a + b;
}

console.log(addInputs("10", "20")); // 30
console.log(addInputs("10", "x"));  // "入力が数値ではありません"
JavaScript

例題2:不定形演算の振る舞い確認

数学的に不定な演算がNaNになることを確かめます。

console.log(0 / 0);               // NaN
console.log(Infinity - Infinity); // NaN
console.log(Math.sqrt(-1));       // NaN
JavaScript

例題3:NaN伝播のデバッグ

途中でNaNになった箇所を特定し、デフォルト値に置き換えて計算を継続します。

function safeMultiply(a, b) {
  const ax = Number.isNaN(a) ? 0 : a;
  const bx = Number.isNaN(b) ? 0 : b;
  return ax * bx;
}

console.log(safeMultiply(10, NaN)); // 0
console.log(safeMultiply(NaN, 3));  // 0
console.log(safeMultiply(4, 5));    // 20
JavaScript

まとめ

NaNは「数値ではない」という状態を示す特別な値で、数値計算の途中で不正な入力や不定形の演算が行われたときに現れます。NaNは自分自身とも等しくないため、判定にはNumber.isNaNやObject.isを使います。入力の検証、NaNの除外や置換、デフォルト値の採用といった対策を組み合わせることで、データ処理の安全性を高められます。

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