PHPに限らず 非数( NAN ) は数値でないこと表すために用意された特別な数値のこと
ちょうど null はデータがないことを表す値なのでそれと似たような感じです。
ここではデータがその非数(NAN)かどうかを判定する方法についてまとめてみました。
NANとはそもそも何なのか
NANとは何なのか・・・(「NAN」と「何」がかかってる)
お決まりのつまらないギャグを言ったところで真面目に解説します(笑)
これは 「Not a number」 の略で数値でないことを表すfloat型の値のことです。float型として定義されているのでNAN自体は数値であることに注意
そしてこのNANが発生するのは数学関数などで無効な計算結果が出た場合です。
例えば次がコード内でNANが出てしまう無効な計算例(ちなみに var_export関数 はコード内で使われるそのままの形式で値を表示する関数)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var_export( log( -1 ) ); /// => NAN var_export( sqrt( -4 ) ); /// => NAN var_export( acos(1.5) ); /// => NAN var_export( INF - INF ); /// => NAN var_export( NAN * NAN ); /// => NAN |
log( -1 ) とか sqrt( -4) とか acos( 1.5 ) とかの数学関数で計算できない値、あるいは INF - INF みたいな無限大を使った計算、 NAN * NAN みたいにNAN自身を使った計算でも発生します。
こういう風に無効な計算で返されるのが NAN という値
NAN自体は数として意味を持ちませんが、数学的な関数・処理で予期せぬ計算が発生したときに処理しやすくするために用意されています。
NAN同士を等号で比較するのはNG!
NANを扱う時、特に比較する場合は1つ注意点があります。
それはNAN同士を等号( == や === )で比較してはいけない、ということ
例えば次のようなコードを実行してみればその意味が分かるはずです。
1 2 |
/** NAN同士を比較 */ var_export( NAN === NAN); |
定数同士を比較しているなら true が返ってくると思ってしまいがちですが、なんとこのコードはNAN同士を比較しているにも関わらず false を返してきます。
これはNANが「どんなものとも(NANとさえも)等しくならない値」と定義されているためです。
なので次のコード例のように等号 === でNAN判定をするのは絶対にNG
1 2 3 4 5 6 7 8 |
/** NAN同士の比較のNG例 */ var_export( NAN === log( -1 ) ); /// => false var_export( NAN === sqrt( -4 ) ); /// => false var_export( NAN === acos(1.5) ); /// => false |
コメント内にも書いたようにこういう比較をすると全て false が返ってきてしまいます。なのでNANかどうかを判定するには絶対に === を使わないように要注意!
NAN判定をする正しい方法
ではPHPでNANかどうかを判定するにはどうすればいいのか・・・
という話ですが、単純に is_nan関数 を使えばいいだけです。
この関数の使い方は簡単で判定したい値を渡すだけ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var_export( is_nan( log( -1 ) ) ); /// => true var_export( is_nan( sqrt( -4 ) ) ); /// => true var_export( is_nan( acos(1.5) ) ); /// => true var_export( is_nan( 3.141519 ) ); /// => false var_export( is_nan( 2 * 1024 ) ); /// => false |
is_nan( sqrt( -4 ) みたいに渡された値が非数なら true 、逆に is_nan( 3.141519 ) みたいに数値なら false が返ってくるので簡単に非数判定することができます。
こういう風にNAN判定をするなら必ず is_nan関数 を使うことが必要です。
知っていればどうってことないですが、知らないと等号で比較してしまいがちなので気を付けたいですね。
補足 : 無限大(Infinity)について
ここまででNANの性質とか判定方法について紹介してきました。
等号を使わず is_nan関数 を使用するのが正しいチェックを行うのに重要です。
そしてこれに加えて無限大(INF)も数値の不正チェックでよく使われます。
文字通りfloat型の範囲を超えた場合に数学関数や式から返される値です。
こちらの判定チェックについては次記事で解説しました。
もし無限大になりえる値をチェックする場合はこちらの方法も知っておいて損はありません。
ここまでのまとめ
ということで簡単にここまでの内容まとめ
- 非数(NAN)について
数学関数( log 、 sqrt 、など...)で無効な計算が起きた場合に返される特別な数値
- 等号でNAN比較してはダメ!
常に異なる値を表すので NAN === NAN と比較すると false が返ってきてしまう
なので値のNAN判定をするときは"絶対"に === を使わないように要注意! - is_nan関数を使うのがベスト
例えば is_nan( log(-1) ) のように is_nan関数 をNAN判定に使うのが確実
返り値は非数の場合は true 、数値だった場合は false が返ってくる
間違っても NAN === NAN みたいに等号で比較しないように気を付けましょう。この注意事項はPHP以外の言語でも大体当てはまります。
以上PHPで値が非数(NAN)かどうかを判定する方法についてでした。