通过阅读的ECMAScript 5.1规范,+0
和-0
被区分。
那么为什么+0 === -0
评估为true
?
通过阅读的ECMAScript 5.1规范,+0
和-0
被区分。
那么为什么+0 === -0
评估为true
?
JavaScript 使用IEEE 754 标准来表示数字。来自维基百科:
有符号零是具有相关符号的零。在普通算术中,-0 = +0 = 0。然而,在计算中,一些数字表示允许存在两个零,通常用-0(负零)和+0(正零)表示。这发生在整数的一些有符号数表示中,以及大多数浮点数表示中。数字 0 通常编码为 +0,但可以用 +0 或 -0 表示。
IEEE 754 浮点算术标准(目前由大多数支持浮点数的计算机和编程语言使用)需要 +0 和 -0。零点可以被认为是扩展实数轴的变体,使得 1/−0 = −∞ 和 1/+0 = +∞,除以零仅对 ±0/±0 和 ±∞/±∞ 未定义.
该文章包含有关不同表示形式的更多信息。
所以这就是为什么从技术上讲,必须区分两个零的原因。
但是,
+0 === -0
评估为真。这是为什么 (...) ?
这种行为在第 11.9.6 节中明确定义,严格相等比较算法(部分强调我的):
比较
x === y
,其中x
和y
是值,产生true或false。这样的比较如下:(...)
如果 Type(x) 是 Number,则
- 如果 x 是 NaN,则返回 false。
- 如果 y 是 NaN,则返回 false。
- 如果 x 与 y 的 Number 值相同,则返回 true。
- 如果 x 为 +0 且 y 为 -0,则返回 true。
- 如果 x 为 -0 且 y 为 +0,则返回 true。
- 返回假。
(...)
(+0 == -0
顺便说一句,这同样适用。)
将+0
和-0
视为平等似乎是合乎逻辑的。否则我们将不得不在我们的代码中考虑到这一点,而我个人不想这样做;)
笔记:
ES2015 引入了一种新的比较方法,Object.is
. Object.is
明确区分-0
和+0
:
Object.is(-0, +0); // false
我会将此添加为答案,因为我忽略了 @user113716 的评论。
您可以通过执行以下操作来测试 -0:
function isMinusZero(value) {
return 1/value === -Infinity;
}
isMinusZero(0); // false
isMinusZero(-0); // true
我刚刚遇到一个例子,其中 +0 和 -0 的行为确实非常不同:
Math.atan2(0, 0); //returns 0
Math.atan2(0, -0); //returns Pi
小心:即使在像 -0.0001 这样的负数上使用 Math.round 时,它实际上也会是 -0 并且可能会搞砸一些后续计算,如上所示。
解决这个问题的快速而肮脏的方法是这样做:
if (x==0) x=0;
要不就:
x+=0;
如果它是 -0,这会将数字转换为 +0。
在用于在 JavaScript 中表示 Number 类型的IEEE 754 标准中,符号由一位表示(1 表示负数)。
因此,每个可表示的数字都存在负值和正值,包括0
。
这就是为什么-0
和 都+0
存在的原因。
回答原标题Are +0 and -0 the same?
:
brainslugs83
(在回答的评论中Spudley
)指出了一个重要的情况,其中 JS 中的 +0 和 -0 不相同 - 实现为函数:
var sign = function(x) {
return 1 / x === 1 / Math.abs(x);
}
除了标准之外,这将Math.sign
返回 +0 和 -0 的正确符号。