为什么键入NaN返回“数字”?
只是出于好奇。
typeof NaN
是编号似乎不是很合乎逻辑。 就像NaN === NaN
或NaN == NaN
顺便返回false。 这是JavaScript的特性之一,还是会有这个原因呢?
编辑:谢谢你的答案。 尽pipe如此,让他们头脑不是一件容易的事情。 阅读答案和维基我更了解,但仍然是一个像
与NaN的比较总是返回一个无序的结果,即使与自己比较。 比较谓词是信令或非信令,信令版本表示这种比较的无效例外。 等式和不等式谓词是非信号的,所以x = x返回false可以用来testingx是否是安静的NaN。
只是让我的头旋转。 如果有人能把这个翻译成人类(而不是math家)可读的语言,那么我将会很有成就感。
这意味着不是一个数字。 这不是javascript的一个特点,而是一般的计算机科学原理。
来自http://en.wikipedia.org/wiki/NaN :
有三种返回NaN的操作:
使用NaN作为至less一个操作数
不确定的forms
- 分0/0,∞/∞,∞/-∞,-∞/∞和-∞/-∞
- 乘法0×∞和0×∞
- 功率1 ^∞
- 加∞+(-∞),(-∞)+∞和等价减法。
实际操作复杂的结果:
- 负数的平方根
- 负数的对数
- 90度(或π/ 2弧度)的奇数倍的切线
- 数字的反正弦或余弦小于-1或大于+1。
所有这些值可能不一样。 NaN的简单testing是testingvalue == value
是错误的。
那么, NaN
仍然是一个数字types ,尽pipe它实际上代表了非数字:-)
NaN
只是意味着特定的值不能在数字types的限制内表示(尽pipe对于所有必须四舍五入以适合的数字可以这么说,但是NaN
是特殊情况)。
特定的NaN
不被认为与另一个NaN
相等,因为它们可能是不同的值。 然而, NaN
仍然是一个数字types,就像2718或31415。
至于你更新的问题,以外行的话来解释:
与NaN的比较总是返回一个无序的结果,即使与自己比较。 比较谓词是信令或非信令,信令版本表示这种比较的无效例外。 等式和不等式谓词是非信号的,所以x = x返回false可以用来testingx是否是安静的NaN。
所有这些意思是(分解成部分):
与NaN的比较总是返回一个无序的结果,即使与自己比较。
基本上,一个NaN
不等于任何其他的数字,包括另一个NaN
,甚至包括它本身 。
比较谓词是信令或非信令,信令版本表示这种比较的无效例外。
试图在一个NaN
和另一个数字之间进行比较(小于,大于等)操作可能导致exception被抛出(信令)或者仅仅因为结果(非信令或者安静)而变为假。
等式和不等式谓词是非信号的,所以x = x返回false可以用来testingx是否是安静的NaN。
testing相等(等于,不等于)不会发出信号,所以使用它们不会引起exception。 如果你有一个规则的数字x
,那么x == x
将始终为真。 如果x
是NaN
,那么x == x
将始终为假。 它给你一个轻松(安静地)检测NaN
的方法。
ECMAScript(JavaScript)标准指定Numbers
是IEEE 754浮点数,其中包括NaN
作为可能的值。
ECMA 262 5e第4.3.19节 :数字值
原始值对应于双精度64位二进制格式IEEE 754值。
ECMA 262 5e第4.3.23节 :NaN
数字值是IEEE 754“非数字”值。
IEEE 754维基百科
IEEE标准的浮点运算是由电气和电子工程师协会制定的技术标准,也是浮点运算最广泛使用的标准[…]
标准定义
- 算术格式 :由有限数字(包括带符号的零和次正数),无穷大和特殊的“非数字”值(NaN)组成的二进制和十进制浮点数据集,
[…]
typeof NaN
返回'number'
因为:
-
ECMAScript规范说数字types包括NaN:
4.3.20号码types
包括特殊的“非数字”(NaN)值,正无限和负无穷的所有可能的数值的集合
-
所以
typeof
返回:11.4.3操作员的types
生产UnaryExpression :
typeof
UnaryExpression的计算方法如下:- 让val是评估UnaryExpression的结果。
- 如果types ( val )是引用 ,那么
- 如果IsUnresolvableReference ( val )为true ,则返回
"undefined"
。 - 让val是GetValue ( val )。
- 如果IsUnresolvableReference ( val )为true ,则返回
- 根据表20返回Type ( val )确定的string。
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数字types
Numbertypes正好具有18437736874454810627(即2 53 -2 64 +3)个值,表示双精度64位格式IEEE 754值,如IEEE二进制浮点algorithm标准中所规定的,不同之处在于9007199254740990(也就是2 53 -2)IEEE标准中不同的“非数字”值在ECMAScript中表示为一个特殊的NaN值。 (请注意, NaN值由程序expression式
NaN
。)
NaN是一个有效的浮点值( http://en.wikipedia.org/wiki/NaN )
NaN === NaN是错误的,因为它们不一定是相同的非数字
NaN != NaN
因为它们不需要同一个非数字。 因此它有很大的意义……同样为什么花车有+0.00和-0.00是不一样的。 舍入可能会做,他们实际上不是零。
至于typeof,则取决于语言。 而大多数语言会说,NaN是一个浮点数,双精度或数字,取决于它们如何分类…我知道没有语言会说这是一个未知的types或null。
NaN
代表不是数字 。 它是一个数值数据types的值(通常是浮点types,但并不总是),表示无效操作的结果,例如除以零。
虽然它的名字表示它不是一个数字,但是用来保存它的数据types是一个数字types。 所以在JavaScript中,要求NaN
的数据types将返回number
(如alert(typeof(NaN))
清楚地表明)。
JavaScript使用NaN来表示它遇到的任何其他方式不能用其规范来表示的东西。 这并不意味着它不是一个数字。 这只是描述遇到的最简单的方法。 NaN意味着它或者一个引用它的对象不能以任何其他方式用javascript表示。 实际上,这是“未知的”。 “未知”,它不能告诉你它是什么,即使它本身。 它甚至不是它分配给的对象。 它只能告诉你它不是什么东西,而不能用编程语言在math上描述。 由于math是关于数字的,JavaScript代表虚无作为NaN。 这并不意味着它不是一个数字。 这意味着我们不能以任何有意义的方式来阅读它。 这就是为什么它甚至不能自己平等。 因为它没有。
这只是因为NaN
是JS中Number对象的一个属性,它与它是一个数字无关。
想想NAN的最好方法就是它不是一个已知的数字。 这就是为什么NAN!= NAN,因为每个NAN值代表一些独特的未知数。 NAN是必要的,因为浮点数的值范围有限。 在某些情况下,舍入发生在低位丢失的地方,导致看起来象1.0 / 11 * 11!= 1.0这样的无意义。 无限大的NAN是一个很好的例子。
由于我们只有十个手指,所以试图显示大于10的值是不可能的,这意味着这样的值必须是NAN,因为我们已经失去了这个大于10的值的真值。 浮点值也是如此,其中的值超过了浮点数的限制。
NaN
是从types的angular度来看的一个数字,但不是像1,2或329131这样的正常数字。名称“不是数字”是指所表示的值是特殊的并且是关于IEEE格式规范域的事实,不是JavaScript语言的域名。
NaN
一个更好的名字,更精确地描述它的含义,不那么容易混淆,这将是一个数值例外 。 它实际上是另一种被伪装成具有原始types(通过语言devise)的exception对象,同样在它的错误的自我比较中它不被视为原始的。 从哪里混乱。 而只要语言“无法自主”在适当的例外对象与原始数字之间进行select,混乱就会停滞不前。
NaN
对自身的臭名昭着的不平等, ==
和===
都是令人困惑的devise的performance,强制这个exception对象成为一种原始types。 这打破了一个基本原则,即一个原始的价值是唯一确定的 。 如果NaN
被视为例外(其中可能有不同的种类),那么它就不应该被当作原始的“销售”。 如果想成为原始的,那么这个原则就成立了。 只要JavaScript有问题,而且我们无法在两者之间做出真正的决定,那么导致所有相关人员的不必要的认知负担的混乱依然存在。 然而,通过简单地在两者之间进行select,这确实很容易解决:
- 要么使
NaN
成为一个特殊的exception对象,其中包含有关如何产生exception的有用信息,而不是像当前实现的那样抛弃这些信息,导致难以debugging的代码; - 或者使
NaN
成为原始typesnumber
一个实体(可能不那么容易被称为“数字”),在这种情况下,它应该与自身相等并且不能包含任何其他信息; 后者显然是一个劣等的select。
强制NaN
进入number
types的唯一可能的好处是能够将其重新用于任何数字expression式。 然而,这使得它很脆弱的select,因为任何包含NaN
数字expression式的结果将是NaN
,或导致不可预知的结果,如NaN < 0
评估为false
,即返回boolean
而不是保持exception。
即使“事情是这样”,也没有什么能阻止我们为自己做出明确的区分,帮助我们的代码更可预测,更容易debugging。 在实践中,这意味着确定这些例外情况并将其作为例外处理。 不幸的是,这意味着更多的代码,但希望可以通过诸如Flowtype的TypeScript之类的工具来缓解。
然后,我们有了凌乱的安静与嘈杂的又名信号NaN
区别 。 究竟是如何处理exception,而不是exception本身,与其他exception没有什么不同。
同样, Infinity
和+Infinity
是数字types的元素,在实线的扩展中出现,但它们不是实数。 在math上,它们可以用收敛于+
或-Infinity
的实数序列表示。
JavaScript只有一个数字数据types,这是标准的64位双精度浮点数。 一切都是双重的。 NaN是双倍的特殊价值,但它是双倍的。
parseInt
所做的就是将你的string“转换”为一个数字数据types,所以结果总是 “数字”。 只有当原始string不可parsing时,其值才会是NaN。
数字types的特殊值是POSITIVE_INFINITY
为什么? 按devise
NaN仍然是一个数字types,但它代表的值不能表示一个有效的数字。
因为NaN是一个数字数据types。
我们可以认为NaN是一个特例。 在这种情况下,NaN的对象代表一个没有math意义的数字。 像INFINITE等math中还有其他一些特例对象。
你仍然可以用它做一些计算,但这会产生奇怪的行为。
更多信息在这里: http : //www.concentric.net/~ttwang/tech/javafloat.htm (基于Java,不是JavaScript)
你必须爱上Javascript。 它有一些有趣的小怪癖。
大部分的怪癖可以从逻辑上停下来解释,或者如果你对数论有一定的了解,但是如果你不了解它们的话,它们仍然可以把你赶出去。
顺便说一句,我build议阅读http://wtfjs.com/的其余部分; – 这里有更多有趣的怪癖!
NaN的值实际上是Number.NaN,因此当你问这是一个数字时,它会说是。 你通过使用isNaN()调用做了正确的事情。
有关信息,NaN也可以通过对数字进行操作来返回,这些数字没有像零或负数的平方根那样被分割。
如果使用jQuery,我更喜欢isNumeric
检查types:
console.log($.isNumeric(NaN)); // returns false console.log($.type(NaN)); // returns number