typeof NaNが 'number'を返すのはなぜですか?


166

単なる好奇心から。

typeof NaN数というのはあまり論理的ではないようです。ちなみにfalseと同じように、NaN === NaNまたはNaN == NaNfalseを返します。これはJavaScriptの特性の1つですか、それとも理由がありますか?

編集:回答ありがとうございます。でも、頭を動かすのは簡単なことではありません。解答とウィキを読んで、私はもっと理解しましたが、それでも、次のような文

NaNとの比較は、それ自体と比較した場合でも、常に順序付けされていない結果を返します。比較述語はシグナリングまたは非シグナリングのいずれかであり、シグナリングバージョンはそのような比較に対して無効な例外を通知します。等式と不等式の述語は非シグナリングであるため、x = xがfalseを返すことを使用して、xが静かなNaNかどうかをテストできます。

頭を回し続けます。誰かがこれを(たとえば、数学者ではなく)人間が読める言語で翻訳できるとしたら、私は感謝しています。


17
+1:「NaNは数値ですが、数値ではありません。ハム...何ですか?!」
ereOn

11
さらなる楽しみのために; (NaN!== NaN)== true
Alex K.

1
さらに楽しい(しかし、考えてみると、isNaNはブール値を返します):isNaN(parseInt( 'nodice'))=== isNaN(parseInt( 'someOtherNaN'))=== true;
KooiInc 2010年

1
jQueryを使用する場合isNumericは、タイプをチェックするよりも$.isNumeric(NaN); falseを返します。ここで、as $.type(NaN);は数値を返します。api.jquery.com/jQuery.isNumeric
Justin

3
プロの数学者として、私はその文は数学の正確な言語とほとんど共通点がないと言わなければなりません。
Dmitri Zaitsev

回答:


53

数字ではないという意味です。これはJavaScriptの特殊性ではなく、一般的なコンピュータサイエンスの原則です。

http://en.wikipedia.org/wiki/NaNから:

NaNを返す操作には3種類あります。

少なくとも1つのオペランドとしてNaNを使用する演算

不定形

  • 分割0/0、∞/∞、∞/ −∞、−∞ /∞、および−∞ / −∞
  • 乗算0×∞および0×−∞
  • パワー1 ^∞
  • 加算∞+(−∞)、(−∞)+∞および同等の減算。

複雑な結果を伴う実際の操作:

  • 負の数の平方根
  • 負の数の対数
  • 90度の奇数倍数(またはπ/ 2ラジアン)のタンジェント
  • -1未満または+1より大きい数値の逆サインまたはコサイン。

これらの値はすべて同じではない場合があります。NaNの簡単なテストは、value == valuefalse をテストすることです。


46
さらに簡単なテストですisNaN(value)
Alsciende

4
@Alsciendeそれは同等ではありません。 isNaN(undefined)が返されますがtrue、これundefined == undefinedも真です。同じことは、を除く他のすべての非数値型にも当てはまりnullます。
Andy

7
つまり、が本当にvalue !== valueかどうかをテストする最も短い方法です。valueNaN
Andy

1
@Andy、あなたは正しいようです。さて、それは特異性です。
Alsciende 2015

2
これらの値が存在しないため、「これらの値は同じではない可能性があります」というフレーズは意味を持ちません。
Dmitri Zaitsev

103

まあ、それは実際にはNot-A-Numberを表すという事実にもかかわらず、NaNまだ数値型です :-)

NaN数値タイプの制限内で特定の値を表すことができないことを意味します(これNaNは、四捨五入する必要があるすべての数値で言えることですが、特殊なケースです)。

特定の値は異なる場合があるため、特定の値は別の値NaNと等しいとは見なされませんNaN。ただし、NaN2718や31415と同様に、数値型のままです。


素人の言葉で説明する更新された質問について:

NaNとの比較は、それ自体と比較した場合でも、常に順序付けされていない結果を返します。比較述語はシグナリングまたは非シグナリングのいずれかであり、シグナリングバージョンはそのような比較に対して無効な例外を通知します。等式と不等式の述語は非シグナリングであるため、x = xがfalseを返すことを使用して、xが静かなNaNであるかどうかをテストできます。

これはすべて(部分に分解)です。

NaNとの比較は、それ自体と比較した場合でも、常に順序付けされていない結果を返します。

基本的に、a NaNは、他の数値を含む他の数値NaNとは異なります

比較述語はシグナリングまたは非シグナリングのいずれかであり、シグナリングバージョンはそのような比較に対して無効な例外を通知します。

a NaNと別の数値の間で比較(より小さい、より大きいなど)操作を実行しようとすると、例外がスローされる(シグナリング)か、結果としてfalseになる(非シグナリングまたはクワイエット)場合があります。

等式と不等式の述語は非シグナリングであるため、x = xがfalseを返すことを使用して、xが静かなNaNであるかどうかをテストできます。

等しいかどうか(等しい、等しくない)のテストは決して通知しないので、それらを使用しても例外は発生しません。あなたが定期的に数を持っている場合xは、x == x常にtrueになります。場合xNaNは、x == x常にfalseとなります。NaN簡単に(静かに)検出する方法を提供します。


1
良い説明ですが、最後の2つの文には同意しません。xがNaNかどうかを確認するより良い方法は、isNaN()関数を使用することです
Carlos Barcelona

@DominicRodgerはここで私はそれについて考えています:typeof a === 'number'「aはIEEE 754フロートとして内部的に保存されています」
Andy

1.0 / 0.0または2.0 / 0.0の異なる値で生成できる場合、なぜInfinity === Infinity戻りますか?trueInfinity
Hashem Qolami 2016年

1
@Hashem、それらは同じ無限大と見なされている可能性が高いためです。除算を繰り返し減算として扱うと、2から始めても1から始めても違いはありません。ゼロに到達する(正確には、到達しない)のに必要なステップ数と同じです。私は数学の達人が何を理解してい私は疑う無限の異なるクラスをが、(1)1/0及び2/0(以外のIEEE754で無限大の唯一のクラスがあります同じクラスに置き、(2)+/-コースのは)。
paxdiablo 2016年

1
これらの例外的な「実際の数」を意味のある方法で定義する方法を私は知りません。数学では、負数の対数と根は、実数を複素数に拡張することによってのみ取得でき、それらは複数の値に評価0/0され、その「値」は集合全体であると言う以外に意味のある方法で定義されていません。数の。そして、それらが定義されていても、はとMath.log(-1) == Math.log(-1)評価されfalseます。したがって、「実際の数」が他にないだけでなくNaN、たとえあったとしても、それらは比較には使用されませんでした。
Dmitri Zaitsev 2016年

20

ECMAScript(JavaScript)標準でNumbersは、IEEE 754浮動小数点数を指定しNaNます。これは、可能な値として含まれます。

ECMA 262 5eセクション4.3.19:数値

倍精度64ビットバイナリ形式のIEEE 754値に対応するプリミティブ値。

ECMA 262 5eセクション4.3.23:NaN

IEEE 754の「Not-a-Number」値である数値。

ウィキペディアのIEEE 754

浮動小数点演算のIEEE標準は、米国電気電子学会によって確立された技術標準であり、浮動小数点計算で最も広く使用されている標準です[...]

標準は、

  • 算術フォーマット:有限数(符号付きゼロと非正規数を含む)、無限大、特別な「非数」値(NaN)で構成される2進および10進浮動小数点データのセット

[...]


8

typeof NaN次の'number'理由で戻ります:

  • ECMAScript仕様によると、数値型にはNaNが含まれています。

    4.3.20数値型

    特別な「Not-a-Number」(NaN)値、正の無限大、負の無限大を含むすべての可能な数値のセット

  • それtypeofに応じて戻ります:

    11.4.3 typeof演算子

    プロダクションUnaryExpressiontypeof UnaryExpressionは次のように評価されます。

    1. してみましょうvalが評価した結果であるUnaryExpressionを
    2. 場合タイプvalが)あるリファレンス、その後、
      1. 場合IsUnresolvableReferencevalが)である、リターン"undefined"
      2. してみましょうヴァルことGetValueメソッドヴァル)。
    3. リターン文字列によって決定されるタイプvalを表20によります)。

                    Table 20 — typeof Operator Results
    ==================================================================
    |        Type of val         |              Result               |
    ==================================================================
    | Undefined                  | "undefined"                       |
    |----------------------------------------------------------------|
    | Null                       | "object"                          |
    |----------------------------------------------------------------|
    | Boolean                    | "boolean"                         |
    |----------------------------------------------------------------|
    | Number                     | "number"                          |
    |----------------------------------------------------------------|
    | String                     | "string"                          |
    |----------------------------------------------------------------|
    | Object (native and does    | "object"                          |
    | not implement [[Call]])    |                                   |
    |----------------------------------------------------------------|
    | Object (native or host and | "function"                        |
    | does implement [[Call]])   |                                   |
    |----------------------------------------------------------------|
    | Object (host and does not  | Implementation-defined except may |
    | implement [[Call]])        | not be "undefined", "boolean",    |
    |                            | "number", or "string".            |
    ------------------------------------------------------------------

この動作は、浮動小数点演算に関するIEEE標準(IEEE 754)に準拠しています。

4.3.19数値

倍精度64ビットバイナリ形式のIEEE 754値に対応するプリミティブ値

4.3.23 NaN

IEEE 754の「Not-a-Number」値である数値

8.5数値タイプ

数値型には正確に18437736874454810627(つまり、2 53 -2 64 +3)の値があり、9007199254740990(つまり、2 53 −2)IEEE標準の個別の「Not-a-Number」値は、ECMAScriptで単一の特別なNaN値として表されます。(NaN値はプログラム式によって生成されることに注意してくださいNaN。)


5

NaNは有効な浮動小数点値です(http://en.wikipedia.org/wiki/NaN

NaN === NaNはfalseです。これは、必ずしも同じ非数ではないためです。


1
申し訳ありませんが、それについて考えるのは良い方法ではありません。「必ずしも同じ非数値ではない」とは、それらが常に異なることを意味するものではなく、それらを比較するとfalseが返されるはずです。NaNを定量化せずに、ナレッジベースの奇妙な点として考えてください。
デイブ

1
では、なぜすべてInfinityのがどういうわけか同一なのでしょうか。何かご意見は?
Hashem Qolami 2016年

5

NaN != NaN同じ番号ではないためです。したがって、それは非常に理にかなっています...また、フロートに+0.00と-0.00の両方が同じではない理由もあります。丸めにより、実際にはゼロにならない場合があります。

typeofに関しては、それは言語に依存します。そして、ほとんどの言語は、NaNがそれを分類する方法に応じて浮動小数点数、倍精度浮動小数点数、または数値であると言います...これが不明な型またはnullであると言う言語はありません。


1
ええ、考慮してください:var x = parseInt( 'no dice')、y = x; 今、私は両方のNaNはまったく同じだと思いますか?しかし、いいえ、x === yもfalseを返します。
KooiInc

はい、しかしあなたは確かではあり得ないので、それらは同じではありません。これは、データベースのNULL可能ロジックと同じロジックです。多くの人々はそれらを他のプログラミング言語からのnullポインターと同じと考えていますが、実際にはまったく異なるセマンティクスを持っています。それらは「不明」であるため、あるNULL値と別のNULL値との比較は常にfalseです。NULL値に対して計算を行うと、結果はNULLになります。代わりにUNKNOWNと呼ばれる値の観点から見てみてください
Cine

タイプnumberとして NaNは、プリミティブであり、その値によって一意に決定されます。
Dmitri Zaitsev 2016年

4

NaNNot a Numberの略です。これは、ゼロによる除算などの無効な演算の結果を表す数値データ型(通常は浮動小数点型ですが、常にではない)の値です。

その名前は数値ではないことを示していますが、それを保持するために使用されるデータ型は数値型です。したがって、JavaScriptでは、のデータ型を要求するNaNnumberalert(typeof(NaN))明確に示されているように)戻ります。


実際にゼロで除算することは評価されInfinityませんNaN
Dmitri Zaitsev '29

2

JavascriptはNaNを使用して、遭遇するあらゆるものを表現しますが、その仕様では他の方法では表現できません。数字ではないという意味ではありません。それは出会いを説明する最も簡単な方法です。NaNは、それまたはそれを参照するオブジェクトをJavaScriptで他の方法で表すことができなかったことを意味します。実際には、「不明」です。「不明」であるため、それが何であるか、それがそれ自体であっても、それを伝えることはできません。割り当てられているオブジェクトでさえありません。それはあなたがそれが何でないかをあなたに伝えることができるだけであり、そして非または無はプログラミング言語で数学的にのみ記述することができます。数学は数値に関するものなので、JavaScriptはNaNとして何も表さない。それが数字ではないという意味ではありません。それは意味のある他の方法でそれを読むことができないことを意味します。それができる理由です それ自体に等しい。ないので。


2

のより適切な名前はNaN、その意味をより正確に、混乱を避けて説明したものですが、数値の例外になります。これは、(言語設計により)プリミティブ型を装った別の種類の例外オブジェクトであり、偽の自己比較ではプリミティブとして扱われません。そこから混乱。そして、適切な例外オブジェクトプリミティブ数値のどちらかを選択する言語が「気にしない」限り、混乱は残ります。

NaNそれ自体の悪名高い非等号は、両方とも=====この例外オブジェクトをプリミティブ型にすることを強制する、混乱を招く設計の現れです。これは、プリミティブがその値によって一意に決定されるという基本原則を破りますNaN例外として見なされることが望ましい場合(その種類は異なる場合があります)、プリミティブとして「販売」しないでください。そしてそれが原始的であることが望まれるならば、その原則は成り立たなければなりません。それが壊れている限り、JavaScriptのように、2つを実際に決定することができない限り、関係者全員に不要な認知的負荷をもたらす混乱が残ります。ただし、どちらかを選択するだけで簡単に修正できます。

  • NaN現在実装されているものとしてその情報を破棄するのではなく、例外がどのように発生したかに関する有用な情報を含む特別な例外オブジェクトを作成して、デバッグがより困難なコードにつながる。
  • またはNaN、プリミティブタイプのエンティティを作成しますnumber(これは、混乱を招くことなく「数値」と呼ばれる可能性があります)。後者は明らかに劣った選択です。

型に強制NaNすることの唯一の考えられる利点は、numberそれを任意の数値式に戻すことができることです。ただし、を含む数値式の結果は、またはに評価するなどの予測できない結果、つまり例外を保持せずに戻るため、NaNどちらを選択するかが不安定になります。NaNNaN < 0falseboolean

そして、「物事はありのままである」としても、コードをより予測可能かつより簡単にデバッグできるようにするために、私たちが自分で明確に区別することを妨げるものはありません。実際には、それはそれらの例外を識別して例外として扱うことを意味します。残念ながら、これはより多くのコードを意味しますが、うまくいけば、FlowtypeのTypeScriptなどのツールによって軽減されるでしょう。

そして、私たちは乱雑な静かな対ノイズの多い信号のNaN区別があります。これは本当に例外の処理方法に関するものであり、例外自体ではなく、他の例外と何の違いもありません。

同様に、Infinityおよび+Infinity、実線延長で発生する数値型の要素ですが、実数ではありません。数学的には、+またはに収束する実数列で表すことができます-Infinity


1

これは単にNaNがJSのNumberオブジェクトのプロパティであるため、数値であることとは何の関係もありません。


他のすべてのオブジェクトと同様に、Numberは任意のタイプのプロパティを持つことができます。Number.fu = "bar"; alert(typeof Number.fu);
アルシエンデ2010年

NaNに格納されている値Number.NaNではありません。NaN数値型のプリミティブ値です。さらに、の値はNumber.NaNですがNaN、それは無関係です。
Oriol

1

NANを考える最良の方法は、既知の数ではないということです。そのため、NAN!= NANは、各NAN値が一意の不明な数値を表すためです。浮動小数点数の値の範囲は限られているため、NANが必要です。場合によっては、下位ビットが失われる丸めが発生し、1.0 / 11 * 11!= 1.0のような無意味に見えるものにつながります。本当に大きい大きな値はNANであり、無限大がその好例です。

指が10本しかないため、10より大きい値を表示しようとすることは不可能です。つまり、10より大きい値の真の値を失ったため、そのような値はNANである必要があります。同じことが浮動小数点値にも当てはまり、値は浮動小数点数で保持できる値の制限を超えます。


無限大はNaNで表されません。範囲外の数値を表現しようとすると、切り捨てられる(max / -inf)または切り上げられる(min / + inf)。
OrangeDog 2014


1

NaNはタイプの観点からの数値ですが、1、2、329131などの通常の数値ではありません。「数値ではないという名前は、表される値が特別であり、IEEE形式仕様ドメインに関するものであり、 JavaScript言語ドメイン。


1

jQueryを使用している場合isNumericは、タイプをチェックするよりも優先します。

console.log($.isNumeric(NaN));  // returns false
console.log($.type(NaN));       // returns number

http://api.jquery.com/jQuery.isNumeric/


ありがとう。Typescriptのパッケージに問題がありisNumberましたutiljQueryプロジェクトで引き続き使用しているため、代わりに提案を使用しました。
Ashok MA

RECの場合は、isNumberからutiltypescriptですのも返すtrueためNaN
Ashok MA

0

Javascriptには、標準の64ビット倍精度浮動小数点である数値データ型が1つだけあります。すべてがダブルです。NaNはdoubleの特別な値ですが、それでもdoubleです。

そのすべてparseInt行い、数値データ型に「キャスト」、あなたの文字列にあるので、結果は常に「番号」。元の文字列が解析可能でなかった場合のみ、その値はNaNになります。



0

NaNは特殊なケースオブジェクトであると主張できます。この場合、NaNのオブジェクトは、数学的に意味のない数値を表します。数学には、INFINITEなどの特別なケースオブジェクトがいくつかあります。

あなたはまだそれを使っていくつかの計算をすることができますが、それは奇妙な振る舞いを生み出します。

詳細はこちら:http : //www.concentric.net/~ttwang/tech/javafloat.htm(javascriptではなく、javaベース)


0

あなたはJavascriptを愛する必要があります。それはいくつかの興味深い小さな癖があります。

http://wtfjs.com/page/13

これらの癖のほとんどは、論理的に解くのをやめた場合、または数論について少し知っている場合に説明できますが、それでもあなたがそれらについて知らない場合でも、あなたを見つけることができます。

ちなみに、残りのhttp://wtfjs.com/を読むことをお勧めします -これよりも興味深い癖がたくさんあります!


0

値NaNは実際にはNumber.NaNなので、数値かどうかを尋ねると、yesと表示されます。isNaN()呼び出しを使用して正しいことを行いました。

ちなみに、NaNは、ゼロによる除算や負の数の平方根のように定義されていない数値に対する演算でも返すことができます。


「価値」ってどんな意味?NaN == Number.NaNに評価されfalseます!
Dmitri Zaitsev 2016年

@DmitriZaitsevスレッドを読みましたか?(parseInt( "nan")== Number.NaN)の場合は試しましたか?また、!=を試して、表示される内容を確認してください。
ロブ・

申し訳ありませんが、愚かなNaN==NaN存在を忘れてしまったfalse、それは誰もが苦しむようにそれを発明したのはサディストだったに違いありません。
Dmitri Zaitsev

0

文字列を数値に変換していると想像してください:

Number("string"); // returns NaN

データタイプを数値に変更しましたが、その値は数値ではありません!


あなたは質問の要点を逃したようです。NaNである数値タイプ。問題はその理由を尋ねることです。
クエンティン

@Quentin最後の行で説明しました。
アミールFo

-1

POSITIVE_INFINITYのような数値型の特別な値です

どうして?意図的に

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.