NaNとは?プログラムで「数値でない」を表す特殊な値の正体

システム開発・テクノロジー
NaNとは?ざっくりと3行で
  • Not a Number(数値でない)の略で、0÷0・無効な数値演算・不正なデータ変換の結果として発生する「数値として表現できない」ことを示す特殊な値のこと
  • JavaScriptでは「typeof NaN === “number”」とNaNが数値型(Number)として扱われるという直感に反する仕様があり、「NaN === NaN」がfalseになるという特殊な性質を持つ
  • プログラムでNaNが発生したまま計算を続けると「感染」して次々とNaNが伝播する性質があるため、入力値のバリデーションとNaNチェックを確実に行うことが重要だ

【深掘り】これだけ知ってればOK!

NaNが発生する典型的なパターンを理解しよう。0÷0:数学的に定義できない。無限大-無限大:不定形。文字列を数値に変換できない場合:JavaScriptで「parseInt(‘abc’)」は NaN になる。負の数の平方根:実数の範囲では定義できない(複素数になる)。IEEE 754浮動小数点数規格でNaNは正式に定義されており、全ての現代プログラミング言語でサポートされている。

JavaScriptのNaNの特殊な性質を理解しよう。まず「typeof NaN === ‘number’」がtrueになるという点だ。NaNは数値型でありながら「数値でない」という矛盾した仕様だ。次に「NaN === NaN」がfalseになる。NaNは自分自身とも等しくならない唯一の値だ。このためNaNの判定には「Number.isNaN(value)」または「isNaN(value)」を使う必要がある。

Pythonでは「import math; math.nan」でNaNを表現できる。「float(‘nan’)」でも生成できる。PythonのNaNはJavaScriptと同様に「math.nan == math.nan」がFalseになる。Pandasのデータ分析ではNaN(欠損値)の扱いが重要で、「df.isna()」「df.dropna()」「df.fillna()」などのメソッドで欠損値を処理する。

データ分析でNaNを放置すると計算結果が全てNaNに「感染」する問題が起きる。例えばpandasのデータフレームでNaNが含まれる列の平均を計算すると、デフォルトではNaNを除外して計算するが、NumPyの「np.mean()」はNaNが含まれるとNaNを返す。np.nanmean()を使うとNaNを除外して平均を計算できる。

NaNの伝播は実務上のバグの原因になりやすい。ある数値フィールドにNaNが混入した状態で計算を続けると、その計算結果もNaNになり、さらに次の計算もNaNになるという連鎖が起きる。最終的に「なぜか結果がNaNになっている」という状態になり原因が追いにくくなる。入力バリデーションの段階でNaNを検出・除外することが根本的な対策だ。

よくある誤解

NaN === NaN でtrue判定できると思っている

NaNは自分自身とも等しくならない唯一の値だ。「NaN === NaN」はfalseを返す。NaNの判定には必ず「Number.isNaN(value)」(JavaScript)または「math.isnan(value)」(Python)を使う必要がある。

typeof NaN は「NaN」や「undefined」を返すと思っている

JavaScriptで「typeof NaN」は「number」を返す。NaNは数値型(Number型)として分類されるという直感に反する仕様だ。「数値でない(Not a Number)」という名前でありながら数値型であるというIEEE 754の仕様に由来する。

会話での使われ方

ITKAGYO運営者デプロイ太郎のアイコン画像

このAPIレスポンスのageフィールドがたまにNaNになっています。parseInt()でパースしているはずなのに。文字列じゃないか確認してください。

フロントエンドエンジニアがAPIレスポンスのデータ型の問題を指摘している場面。parseInt()に非数値文字列が渡されるとNaNになる。

ITKAGYO運営者デプロイ太郎のアイコン画像

データ分析のコードで平均値がNaNになっていました。pandasのdropna()で欠損値を除外してから計算し直してください。

データサイエンティストが欠損値の処理漏れを指摘している場面。NaNの伝播で計算結果が全てNaNになっていた。

ITKAGYO運営者デプロイ太郎のアイコン画像

JavaScriptでvalue === NaNで判定しようとしていますが、NaNはNaN自身と等しくならないのでNumber.isNaN(value)を使ってください。

コードレビューでシニアエンジニアがNaNの正しい判定方法を指摘している場面。

【まとめ】3つのポイント

  • 数値として表現できない演算結果を表すIEEE 754準拠の特殊値:0÷0・無効な文字列の数値変換・不定形の演算などで発生し、全ての現代プログラミング言語でサポートされる標準的な浮動小数点数の仕様だ
  • NaN === NaN がfalseになる性質を必ず理解する:NaNは自分自身とも等しくならない唯一の値であるため等値演算子での判定が使えず、Number.isNaN()やmath.isnan()などの専用関数を使う必要がある
  • NaNの伝播を防ぐために入力バリデーションで早期に検出する:NaNが含まれた状態で計算を続けると結果が次々とNaNに感染するため、データ入力・API受信・型変換の段階でNaNを検出・除外することが根本的な対策だ

よくある質問

Q
JavaScriptでNaNを正しく判定するにはどうすればいいですか?
A

「Number.isNaN(value)」を使うことを推奨します。グローバルの「isNaN(value)」は引数を数値に変換してから判定するため、「isNaN(‘hello’)」がtrueになるなど意図しない結果になることがあります。Number.isNaN()は型変換を行わず厳密にNaNのみtrueを返します。

Q
Pythonでnp.mean()がNaNを返す場合の対処法は?
A

np.nanmean()を使うとNaNを除外して平均を計算します。pandasではdf[‘column’].mean()がデフォルトでNaNをスキップします。先にdf.dropna()で欠損値を除外するか、df.fillna(0)でNaNを0に置換してから計算する方法もあります。

Q
NaNとundefinedとnullの違いは何ですか?(JavaScript)
A

nullは「意図的に値がない」ことを表します。undefinedは「変数が定義されているが値が代入されていない」状態です。NaNは「数値演算の結果が数値で表現できない」状態です。typeof null === ‘object’、typeof undefined === ‘undefined’、typeof NaN === ‘number’という点も覚えておきましょう。

Q
NaNとInfinityはどう違いますか?
A

Infinityは「無限大」を表す特殊な数値で、1÷0などで発生します。InfinityはNumber型で計算に使え、「Infinity + 1 === Infinity」のように振る舞います。NaNは「数値として表現できない結果」で、計算するとほぼ全てNaNに感染します。「Infinity – Infinity」がNaNになるなど両者が絡むケースもあります。

この用語と一緒に知っておきたい用語

用語 この記事との関連
JavaScript JavaScriptを押さえると本記事の理解がさらに深まります。WebブラウザがネイティブにサポートするプログラミングはJavaScriptのみ。フォームのバリデーション・アニメーション・SPAなどブラウザ上のインタラクションはすべてJavaScriptが担う
データ 本記事のテーマと実務上セットで使われることが多い用語です。コンピュータが処理する数値や文字、画像といった事実や資料そのもの、それがデータだ
Python Pythonとの関係を知ると全体像がつかみやすくなります。シンプルで読みやすい文法を持つ汎用プログラミング言語。AIライブラリ(TensorFlow・PyTorch)・データ分析(pandas・NumPy)・Web開発(Django・FastAPI)まで幅広く使える
バリデーション 本記事のテーマと実務上セットで使われることが多い用語です。ユーザーやシステムが入力したデータが期待する形式・範囲・内容に合致しているかを検証(確認)する処理・仕組みのこと
アイコン アイコンを押さえると本記事の理解がさらに深まります。アプリやファイル、操作ボタンなどをひと目でわかる小さな絵で表したもの、それがアイコンだ

【出典】参考URL

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/NaN :MDN「NaN」の解説
https://docs.python.org/ja/3/library/math.html#math.nan :Python公式「math.nan」のドキュメント
https://ieeexplore.ieee.org/document/8766229 :IEEE 754浮動小数点数規格(NaNの仕様元)

コメント

  1. NaNという言葉に最初に出会ったのは、どんな場面だったでしょうか。仕事・勉強・ニュースなど、きっかけをコメントで聞かせてもらえると励みになります。

「IT用語、難しすぎて心が折れそう……」という方のための、ハードル低めな用語辞典です。

情報レベルは「基礎中の基礎」。会話を止めないためのエッセンスだけを抽出しています。分かりやすさを追求するあまり、時々例え話が暴走しているかもしれませんが、そこは「ほどよく」聞き流していただけると幸いです。
ほどよくIT用語辞典システム開発・テクノロジー
デプロイ太郎のSNSを見てみる!!