コンピュータサイエンスの文脈で言う"NaN"は、"Not a Number"の略である。
しかし、これを素直に「数値以外のデータ」として受け取ると、混乱する羽目になる。
例えばJavaScriptには、isNaN()というメソッドがある。一見すると、何かしらの値を受け取り、それが数値ではない場合にtrue、そうではない場合にfalseを返してくれそうだ。
この解釈は必ずしも間違いではないが、正しくもない。
NaNの意味
"NaN"は、コンピュータが計算した結果、それが数値ではなかった場合に使われる記号である。
例えば0で割ったりとか、Infinityを掛けたりとか、虚数を求めたりとかするとNaNが返される。
NaNは、浮動小数点数の演算の標準規格であるIEEE 754によって定められた。現在の仕様は改訂版のIEEE 754-2008に則っている。
JavaScriptのNaN
JavaScriptのNaNは、グローバルプロパティである。書き換えはできず、オブジェクトのようにプロパティを追加することもできない。
0や1と同じく、実質的にはNumber型のプリミティブ値として扱われる。
また、JavaScriptでNaNが表れるのは、以下の5パターンのいずれかである。
Number型以外の値の、Number型への無理な変換- 実数以外の結果が表れる数値演算
- 無限大が含まれる演算
NaNの含まれる演算- その他、無効な値を数値型として表現しようとする演算
ほか、JavaScriptに限らず、NaNは以下の特徴を持つ。
NaNが含まれる演算の結果は、常にNaNとなるNaNが含まれる関係演算は、常にfalseを返すNaNとNaNも不等となるNaNはfalsyな値である
isNaN()とNumber.isNaN()
NaNとNaNは不等である。なのでif(val === NaN)のような条件文は、仮にvalの中身がNaNであっても常にfalseとなる。
JavaScriptには、渡された値がNaNかどうかを判断する方法が2つある。
isNaN()とNumber.isNaN()である。
かつてはisNaN()のみで賄われていたが、この関数には問題があった。数値以外の値が渡された際に、その値を数値型に変換する、というものだ。
この変換が場合によって予測不明であるために、より厳密にNaNを判断する方法としてNumber.isNaN()が追加された。
ちなみにisNaN()に渡された値は以下のように変換される。
- 数値はそのまま。
undefinedはNaNに変換。nullは0に変換。trueは1に、falseは0に変換。- 文字列は、以下のルールに基づいてパースされ、パースに失敗すると
NaNとなる。- 先頭と末尾の空白・改行は無視される。
- 先頭に
0があっても、8進数としては解釈されない。 - 先頭の
+と-は、符号として許可される。 Inifityと-Infinityは、数値として解釈される。- 空文字やスペースだけの文字列は
0に変換する。 - 読みやすさのための区切り文字(
_)は許可されない。
BigIntsとSymbolはTypeErrorを投げる- オブジェクトの場合は、そのオブジェクトの
[@@toPrimitive]()メソッド、valueOf()メソッド、toString()メソッドを順に呼び出し、プリミティブ値に変換できた段階で数値に変換される。