NaN(Not a Number)とは
NaN(Not a Number、非数、
ナン)は、
コンピュータにおける浮動小数点演算の結果として、不正なオペランドが与えられた場合に発生する特殊な値です。これは、数値として表現できない結果や、計算が意味をなさない状況を示すために用いられます。
NaNの標準規格
1985年に制定された
IEEE 754浮動小数点規格によって、NaNの体系的な仕様が定められました。この規格では、
無限大の表現と共に、NaNが標準化されています。
NaNの種類
NaNには、以下の2つの種類があります。
quiet NaN(qNaN): 不正な操作や値を伝播させるために使用されます。計算結果がNaNとなる場合、そのNaNは後続の計算にも影響を与えます。
signaling NaN(sNaN): 数値計算と記号計算の混合や、浮動小数点演算の拡張など、高度な機能をサポートするために使用されます。sNaNに対する演算は、例外を発生させる可能性があります。
NaNが発生する例
以下のような状況でNaNが発生します。
不定形: 0 ÷ 0 や ∞ ÷ ∞ など、数学的に値が定まらない計算。
負数の平方根:
実数範囲では定義できないため。
虚数となる演算: 負数の対数など。
未定義値: 計算に必要な値が得られていない場合。
無限大が絡む演算: ∞ + (-∞) など、どちらの無限大ともできない計算。
NaNと無限大の違い
浮動小数点数において、NaNと無限大は異なる概念です。どちらも特殊な表現を持ち、演算結果も特殊になります。ただし、文献によっては、両方を含めて「非数」と表現することもありますが、混同を避けるため、明確に区別して扱うことが推奨されます。
IEEE 754規格では、NaNは指数部が全て1、仮数部が0以外のビット列で表現されます。この仮数部のビット列によって、quiet NaNとsignaling NaNを区別します。また、符号ビットによって正負のNaNを表現できますが、多くのアプリケーションでは符号は無視されます。
NaNの伝播
quiet NaNは、演算を通してそのまま伝播します。そのため、計算途中で何度もNaNをチェックする必要はなく、最終結果を調べればNaNの有無がわかります。signaling NaNは、演算時に不正例外を発生させ、デフォルトではqNaNを生成します。
NaNの比較
NaN同士の比較では、自分自身と比較した場合でも「大小不明」となります。等号および不等号による比較は常にfalseを返します。それ以外の大小比較では、NaNがオペランドに含まれると不正例外が発生しますが、規格では非シグナリング版も提供されています。NaNかどうかを判定する関数(isNaN(x))は、シグナリングNaNでも例外を発生させません。
NaNと統計処理
統計関数では、NaNは欠損値として扱われ、計算から無視されることが多いです。
NaNを返す演算
NaNは、以下のような演算で生成される可能性があります。
NaNを引数とする数学関数
不定形(0/0, ±∞/±∞, 0×±∞, ±∞×0, ∞ + (-∞))
結果が
虚数となる演算
また、計算上必要な値が得られない場合、明示的に変数にNaNを代入することがあります。
quiet NaNとsignaling NaN
quiet NaN: 演算中に伝播するだけで、例外を発生させません。
signaling NaN: 多くの操作で不正例外を発生させ、その後qNaNに変化して伝播します。
signaling NaNは、以下のような用途に使用できます。
初期化されていないメモリ領域の検出
プレースホルダーとしての利用
算術アンダーフローやオーバーフローの表現
より高精度な数値の表現
複素数の表現
関数定義におけるNaNの扱い
数値関数がNaNを入力として受け取った場合、その扱いにはいくつかの考え方があります。一つはNaNを伝播させるべきという考え方、もう一つはNaNでない引数で出力が決まる場合はその値を返すという考え方です。IEEE 754規格は後者の立場を取っています。例えば、hypot(±∞, qNaN) は +∞ を返します。pow(1,NaN)は1を返します。
冪乗関数とNaN
冪乗関数には、pow, pown, powr の3種類があります。pow関数は0^0, 1^∞, ∞^0を1と定義しています。pown関数は冪指数が整数に限定され、powr関数は上記の不定形に対してNaNを返します。
固定ビット幅の整数フォーマットでは、不正データを表す方法が明確ではありません。そのため、PerlのBigIntパッケージのように、NaNを文字列として表現する場合があります。
NaNのテキスト表現
NaNのテキスト表現は、プログラミング言語やライブラリによって異なります。例えば、「nan」「NaN」「NaN%」「NAN」「NaNQ」「NaNS」「qNaN」「sNaN」「1.#SNAN」「1.#QNAN」「+nan.0」「-nan.0」「-1.#IND」などがあります。
NaNのエンコード
IEEE 754におけるNaNの表現(エンコード)は以下の通りです。
符号ビット: 任意
指数部: 全て1 (無限大と同じ)
仮数部: 0以外の値
signaling NaNとquiet NaNを区別するため、仮数部の最上位ビットが使用されることが多いです。
NAとの違い
NA(Not Available)は、データが欠損していることを意味するもので、統計分野や
R言語などで使用されます。NaNとは異なる概念で、NaN == NaN が偽なのに対し、NA == NA は NA を返します。
まとめ
NaNは、浮動小数点演算における特殊な値で、不正な演算や未定義の状態を表します。静かなNaNとシグナリングNaNの2種類があり、それぞれエラー伝播や高度な機能に使用されます。NaNを正しく理解し、適切に処理することで、プログラムの信頼性を高めることができます。