阅读ECMAScript 5.1规范,可以发现+0
和-0
是有区别的。
那么为什么+0 === -0
的结果会是true
呢?
文章包含了关于不同表示法的更多信息。有符号零是带有符号的零。在普通算术中,-0 = +0 = 0。然而,在计算中,一些数字表示允许存在两个零,通常用-0(负零)和+0(正零)表示。这在整数的一些有符号数字表示法和大多数浮点数表示法中发生。数字0通常被编码为+0,但可以由+0或-0表示。
浮点运算的IEEE 754标准(目前由大多数支持浮点数的计算机和编程语言使用)要求同时具有+0和-0。可以将这些零视为扩展实数线的变体,使得1 / -0 = -∞和1 / +0 = +∞,仅对±0 / ±0和±∞ / ±∞的除法未定义。
然而,
+0 === -0
的结果为true。为什么会这样(...)?
这种行为在第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。
- 返回false。
(...)
(对于+0 == -0
也是一样的。)
把+0
和-0
视为相等似乎是合理的。否则我们将不得不在代码中考虑这一点,而我个人不想这样做;)
注意:
ES2015引入了一种新的比较方法,Object.is
。 Object.is
明确区分-0
和+0
:
Object.is(-0, +0); // false
1/0 === Infinity; // true
和 1/-0 === -Infinity; // true
。 - user1137161 === 1
和 +0 === -0
,但是 1/+0 !== 1/-0
。多么奇怪! - Randomblue+0 !== -0
好;) 这可能会产生问题。 - Felix Kling0 !== +0
/ 0 !== -0
,这也会导致问题! - Yanick Rochon因为我忽略了@user113716的评论,我会将其作为回答添加。
您可以通过执行以下操作来测试-0:
function isMinusZero(value) {
return 1/value === -Infinity;
}
isMinusZero(0); // false
isMinusZero(-0); // true
e±308
,你的数字只能以非规格化形式表示,并且不同的实现对于是否支持它们在哪里支持它们有不同的意见。关键是,在某些机器上,在某些浮点模式下,你的数字被表示为-0
,而在其他机器上则表示为非规格化数字0.000000000000001e-308
。这样的浮点数,真是太有趣了。 - weaknespase我刚刚遇到了一个例子,在这个例子中,+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相同吗?
简短回答: 取决于您使用的比较运算符。
详细回答:
基本上,我们到目前为止有4种比较类型:
console.log(+0 == -0); // true
console.log(+0 === -0); // true
Object.is
)console.log(Object.is(+0, -0)); // false
console.log([+0].includes(-0)); // true
As a result, just Object.is(+0, -0)
makes difference with the other ones.
const x = +0, y = -0; // true -> using ‘loose’ equality
console.log(x === y); // true -> using ‘strict’ equality
console.log([x].indexOf(y)); // 0 (true) -> using ‘strict’ equality
console.log(Object.is(x, y)); // false -> using ‘Same-value’ equality
console.log([x].includes(y)); // true -> using ‘Same-value-zero’ equality
回答原标题+0和-0是否相同?
:
Spudley
的答案评论中,brainslugs83
指出了一个重要的情况,在JavaScript中,+0和-0不相同 - 它们被实现为函数:
var sign = function(x) {
return 1 / x === 1 / Math.abs(x);
}
除了标准的Math.sign
之外,这将返回+0和-0的正确符号。
true
或者 false
,而不是 -1
和 1
。 - Eugene MalaObject.is
来区分+0和-0,还有一件事,NaN==NaN
。Object.is(+0,-0) //false
Object.is(NaN,NaN) //true
-0
和 +0
的 sign
函数:var sign = x => 1/x > 0 ? +1 : -1;
它与Math.sign
类似,但sign(0)
返回1
,而sign(-0)
返回-1
。
sign(Infinity)
返回 -1
。 - undefined0有两个可能的值(位表示),这并不是唯一的。特别是在浮点数中,这种情况经常发生。因为浮点数实际上是以一种公式的形式存储的。
整数也可以以不同的方式存储。您可以具有带有额外符号位的数字值,因此在16位空间中,您可以存储15位整数值和一个符号位。在此表示中,值1000(十六进制)和0000都是0,但其中一个是+0,另一个是-0。
这可以通过从整数值中减去1来避免,使其范围从-1到-2 ^ 16,但这将很不方便。
更常见的方法是使用“二补码”存储整数,但显然ECMAscript选择不这样做。在这种方法中,数字范围从0000到7FFF正数。负数从FFFF(-1)到8000开始。
当然,相同的规则也适用于更大的整数,但我不想让我的F磨损。;)
+0 === -0
有点奇怪吗?因为现在我们有了 1 === 1
和 +0 === -0
,但是 1/+0 !== 1/-0
... - Randomblue
Object.is
来区分+0和-0。 - Benjamin Gruenbaum