为什么typeof NaN返回“数字”?


166

只是出于好奇。

typeof NaN数字似乎不太合逻辑。顺便说一句,就像NaN === NaNNaN == NaN返回假。这是javascript的特性之一,还是有原因呢?

编辑:谢谢你的回答。但是,要让人们适应并不是一件容易的事。阅读答案和Wiki我了解得更多,但仍然有类似

与NaN的比较始终会返回无序结果,即使与自身进行比较也是如此。比较谓词是信令或非信令,信令版本表示此类比较的无效异常。相等和不相等谓词是无信号的,因此x = x返回false可以用来测试x是否为安静的NaN。

只是让我的头旋转。如果有人可以用人类(而不是数学家)可读的语言来翻译它,我将不胜感激。


16
+1:“ NaN是一个数字,但不是一个数字。哼……什么?!”
ereOn 2010年

11
为了额外的乐趣;(NaN!== NaN)==正确
Alex K. 2010年

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
贾斯汀

3
作为专业的数学家,我必须说句子与精确的数学语言几乎没有共同之处。
德米特里·扎伊采夫

Answers:


53

这意味着不是数字。它不是javascript的特性,而是通用的计算机科学原理。

来自http://en.wikipedia.org/wiki/NaN

返回NaN的操作有以下三种:

以NaN作为至少一个操作数的运算

不确定形式

  • 除法0/0,∞/∞,∞/-∞,-∞/∞和-∞/-∞
  • 乘法0×∞和0×-∞
  • 幂1 ^∞
  • 加法器∞+(-∞),(-∞)+∞和等效减法。

具有复杂结果的实际操作:

  • 负数的平方根
  • 负数的对数
  • 90度(或π/ 2弧度)的奇数倍的切线
  • 小于-1或大于+1的数字的反正弦或余弦。

所有这些值可能不相同。对NaN的简单测试是测试value == value是否为假。


46
一个更简单的测试是isNaN(value)
Alsciende 2010年

4
@Alsciende虽然不一样。 isNaN(undefined)返回true,但undefined == undefined也是如此。除以外的所有其他非数字类型也是如此null
安迪

7
换句话说,value !== value可能是测试是否value为true 的最短方法NaN
安迪

1
@Andy,看来您是对的。现在,这很特殊。
Alsciende 2015年

2
短语“这些值可能不相同”没有意义,因为这些值不存在。
德米特里·扎伊采夫

103

好吧,NaN它仍然是一个数字类型,尽管实际上它代表Not-A-Number :-)

NaN只是意味着不能在数字类型的限制内表示特定值(尽管可以对所有必须四舍五入以适合的数字表示,但这NaN是一种特殊情况)。

一个特定的NaN值不等于另一个NaN值,因为它们可能是不同的值。但是,NaN仍然是数字类型,就像2718或31415一样。


至于您用外行人的术语解释的最新问题:

与NaN的比较始终会返回无序结果,即使与自身进行比较也是如此。比较谓词可以是信令通知,也可以是非信令通知,信令版本表示此类比较无效。等式和不等式谓词是无信号的,因此x = x返回false可以用来测试x是否是安静的NaN。

所有这些手段(分为几部分):

与NaN的比较始终会返回无序结果,即使与自身进行比较也是如此。

基本上,a NaN不等于任何其他数字,包括另一个NaN,甚至包括其自身

比较谓词可以是信令通知,也可以是非信令通知,信令版本表示此类比较无效。

尝试在a NaN和另一个数字之间进行比较操作(小于,大于等),可能会导致引发异常(发出信号)或结果只是错误(未发出信号或安静)。

等式和不等式谓词是无信号的,因此x = x返回false可以用来测试x是否是安静的NaN。

相等性测试(等于,不等于)永远不会发出信号,因此使用它们不会导致异常。如果您有一个固定数字x,那么x == x它将永远是正确的。如果xNaN,则x == x始终为假。它为您提供了一种NaN轻松(安静地)检测的方法。


1
很好的解释,尽管我在最后两句话中不同意:检查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 '16

1
@Hashem,很有可能是因为它们被视为相同的无穷大。将除法视为重复减法,无论您是从2还是1开始都没有区别,达到零(或更准确地说,没有达到)所需的步数相同。我了解数学大师确实具有不同的无穷大类别,但是(1)我怀疑1/0并且2/0处于同一类别,并且(2)IEEE754中只有一类无穷大(+/-当然不是)。
paxdiablo

1
我不知道以任何有意义的方式定义这些例外的“实际数字”的方法。在数学中,对数和负数的根只能通过将实数扩展为复数来获得,在复数中它们计算为多个值,并且0/0没有以任何有意义的方式定义,只能说其“值”是整个集合数字。即使已定义它们,Math.log(-1) == Math.log(-1)仍求值为false。因此,不仅没有“实际数字”,NaN而且即使存在,也没有用于比较。
德米特里·扎伊采夫

20

ECMAScript的(JavaScript的)标准规定,NumbersIEEE 754浮筒,其中包括NaN作为可能的值。

ECMA 262 5e第4.3.19节:数值

对应于双精度64位二进制格式IEEE 754值的原始值。

ECMA 262 5e第4.3.23节:NaN

是IEEE 754“非数字”值的数字值。

维基百科上的IEEE 754

IEEE浮点算法标准是由电气和电子工程师协会建立的技术标准,也是浮点计算最广泛使用的标准[...]

标准定义

  • 算术格式:二进制和十进制浮点数据集,由有限数字(包括带符号的零和次正规数),无穷大和特殊的“非数字”值(NaNs)组成

[...]


8

typeof NaN'number'之所以返回,是因为:

  • ECMAScript规范说Number类型包括NaN:

    4.3.20数字类型

    所有可能的Number值的集合,包括特殊的“非数字”(NaN)值,正无穷大和负无穷大

  • 因此相应地typeof返回:

    11.4.3 typeof运算符

    产生UnaryExpressiontypeof UnaryExpression的评估如下:

    1. val为评估UnaryExpression的结果。
    2. 如果Typeval)是Reference,则
      1. 如果IsUnresolvableReferenceval)为true,则返回"undefined"
      2. valGetValueval)。
    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“非数字”值的数字值

8.5数字类型

Number类型正好具有18437736874454810627(即2 53 −2 64 +3)值,表示IEEE二进制浮点算术标准中指定的双精度64位格式IEEE 754值,但9007199254740990(也就是说,在ECMAScript中,IEEE标准的2 53 -2)个不同的“非数字”值表示为单个特殊的NaN值。(请注意,NaN值由程序表达式产生NaN。)


5

NaN是有效的浮点值(http://en.wikipedia.org/wiki/NaN

NaN === NaN为假,因为它们不一定是相同的非数字


1
抱歉,但是我不得不说这不是考虑的好方法。“不一定是相同的非数字”并不意味着它们总是不同的,比较它们应得出错误的结果。最好不要量化NaN,而只是将其视为我们知识库中的一个奇怪现象。
戴夫

1
那么,为什么所有Infinity的东西都是一样的呢?有什么想法吗?
Hashem Qolami '16

5

NaN != NaN因为它们不是必需的SAME非数字。因此,这很有道理。还有为什么浮点数的+0.00和-0.00都不相同。四舍五入可能会使它们实际上不为零。

至于typeof,这取决于语言。而且大多数语言会说NaN是浮点数,双精度数或数字,具体取决于它们如何对它进行分类……我知道没有语言会说这是未知类型或null。


1
嗯,请考虑:var x = parseInt('no dice'),y = x; 现在我要说两个NaN完全一样吗?但是不,x === y也返回false。
KooiInc 2010年

是的,但是您不能确定,因此它们并不相同。它与数据库中的NULLable逻辑相同。尽管许多人认为它们与其他编程语言的空指针相同,但实际上它们具有完全不同的语义。它们是“ UNKNOWN”,因此一个NULL值与另一个NULL值始终为false。对NULL值进行计算最终会得到结果NULL。尝试从被称为UNKNOWN的值的角度查看它
电影Cine

为类型的numberNaN是原始的,并且因此唯一地由其值确定。
德米特里·扎伊采夫

4

NaN代表Not a Number。它是数字数据类型(通常是浮点类型,但并非总是如此)的值,表示无效操作(例如除以零)的结果。

尽管其名称表明它不是数字,但用于保存它的数据类型是数字类型。因此,在JavaScript中,要求NaN返回will 的数据类型numberalert(typeof(NaN))清楚地证明了这一点)。


其实被零除进行评估,以InfinityNaN
德米特里·扎伊采夫

2

Javascript使用NaN表示遇到的任何内容,而规范无法用其他任何方式来表示。这并不意味着它不是数字。这是描述相遇的最简单方法。NaN表示javascript不能以任何其他方式表示它或引用它的对象。实际上,它是“未知的”。作为“未知”,它无法告诉您它是什么,即使它本身也是。它甚至不是分配给它的对象。它只能告诉您什么不是,而非或虚无只能用一种编程语言来数学地描述。由于数学是关于数字的,因此javascript将虚无表示为NaN。这并不意味着它不是数字。这意味着我们无法以其他任何有意义的方式阅读它。这就是为什么可以 甚至等于自己。因为不是。


2

一个更好的名字NaN,可以更精确地描述其含义,而不会造成混淆,这是一个数字例外。实际上,这是另一种伪装成具有原始类型的异常对象(通过语言设计),在这种情况下,在其错误的自比较中,该异常对象不被视为原始类型。造成混乱的地方。只要语言“不会决定”在适当的异常对象原始数字之间进行选择,混乱就将继续存在。

臭名昭著的非平等NaN于本身,既=====是混淆设计迫使此异常对象形成了一个基本类型的体现。这打破了由原语唯一决定其价值的基本原则。如果NaN希望将其视为例外(可以有不同的种类),则不应将其作为原始出售。如果希望它是原始的,则必须遵守该原则。只要它被破坏了(就像我们在JavaScript中一样),并且我们不能真正在两者之间做出决定,那么对于每个参与人员而言,导致不必要的认知负担的混乱将依然存在。但是,只需在两者之间做出选择,就很容易修复它:

  • 或者创建NaN一个特殊的异常对象,该对象包含有关异常发生的有用信息,而不是像当前实现的那样丢弃该信息,从而导致难以调试的代码;
  • 或创建NaN一个原始类型的实体number(可以较少混淆地称为“数字”),在这种情况下,它应该与自身相等,并且不能包含任何其他信息;后者显然是次等选择。

强迫的唯一可能的优势NaN进入number类型是能够把它放回任何数值表达式。但是,这使之成为易碎的选择,因为包含任何数值表达式的结果NaN将为NaN或导致不可预测的结果,例如对进行NaN < 0求值false,即返回boolean而不是保留异常。

即使“事物就是它们的样子”,也没有什么可以阻止我们为自己做出清楚的区分,以帮助使我们的代码更可预测且更易于调试。实际上,这意味着识别那些例外并将其作为例外处理。不幸的是,这意味着需要更多代码,但是希望可以通过诸如Flowtype的TypeScript之类的工具来减轻这些负担。

然后我们得到了凌乱的安静与嘈杂的信号NaN区别。这实际上是关于异常的处理方式,而不是异常本身,与其他异常没有什么不同。

同样,Infinity+Infinity在实线扩展中出现的数字类型的元素,但它们不是实数。从数学上讲,它们可以由收敛到或的实数序列表示。+-Infinity


1

这仅仅是因为它NaN是JS中Number对象的属性,与它是数字无关。


像其他所有对象一样,Number可以具有任何类型的属性。Number.fu = "bar"; alert(typeof Number.fu);
Alsciende

NaN不是存储在中的值Number.NaN,无论它是什么。NaN是Number类型的原始值。另外,的值Number.NaNNaN,但这无关紧要。
Oriol 2015年

1

想到NAN的最好方法是它不是一个已知的数字。这就是为什么NA​​N!= NAN的原因,因为每个NAN值代表一个唯一的未知数。NAN是必需的,因为浮点数的值范围有限。在某些情况下,舍入会在低位丢失的情况下发生,从而导致看起来像1.0 / 11 * 11!= 1.0这样的废话。大于NAN的真正大值就是一个很好的例子。

假设我们只有十根手指,则不可能尝试显示大于10的值,这意味着这些值必须是NAN,因为我们已经失去了大于10的值的真实值。浮点值也是如此,其中的值超过了浮点数的限制。


NaN不代表无穷大。尝试表示超出范围的数字将四舍五入(至最大/ -inf)或向上(至最小/ + 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/


谢啦。我有问题,isNumberutil打字稿的包。好的,我们仍然jQuery在项目中使用,所以改用您的建议。
Ashok MA

对于REC,isNumberutil打字稿也回报trueNaN
Ashok MA

0

Javascript只有一种数值数据类型,它是标准的64位双精度浮点数。一切都是双重的。NaN是double的特殊值,但它仍然是double。

所有parseInt要做的就是将您的字符串“转换”为数字数据类型,因此结果始终为 “数字”。仅当原始字符串不可解析时,其值为NaN。




0

您必须爱Javascript。它有一些有趣的小怪癖。

http://wtfjs.com/page/13

如果您停止逻辑地解决它们,或者如果您对数论有所了解,那么可以解释大多数这些怪癖,但是,如果您不了解它们,它们仍然可以帮助您。

顺便说一句,我建议您阅读http://wtfjs.com/的其余部分-还有比这个有趣的怪癖!


0

NaN值实际上是Number.NaN,因此当您询问是否为数字时,它将说是。您通过使用isNaN()调用做了正确的事情。

作为参考,NaN也可以通过对未定义的数字进行操作来返回,例如未除以零或负数的平方根。


从什么意义上说它是“价值”?NaN == Number.NaN评估为false
德米特里·扎伊采夫

@DmitriZaitsev您读过主题吗?并且您是否尝试过(parseInt(“ nan”)== Number.NaN)?还可以尝试!=并查看其内容。
罗布

对不起,忘了愚蠢的NaN==NaN生活false,一定是一个使每个人受苦的施虐者。
德米特里·扎伊采夫

0

一个例子

想象一下,我们正在将字符串转换为数字:

Number("string"); // returns NaN

我们将数据类型更改为数字,但其值不是数字!


您似乎错过了问题的重点。NaN数字类型。问题是为什么。
Quentin

@Quentin我在最后一行解释了。
阿米尔·佛

-1

这是数字类型的特殊值,为POSITIVE_INFINITY

为什么?通过设计

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.