+0 和 -0 一样吗?

IT技术 javascript
2021-01-24 00:57:51

通过阅读的ECMAScript 5.1规范+0-0被区分。

那么为什么+0 === -0评估为true

6个回答

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,其中xy是值,产生truefalse这样的比较如下:

(...)

  • 如果 Type(x) 是 Number,则

    1. 如果 x 是 NaN,则返回 false。
    2. 如果 y 是 NaN,则返回 false。
    3. 如果 x 与 y 的 Number 值相同,则返回 true。
    4. 如果 x 为 +0 且 y 为 -0,则返回 true。
    5. 如果 x 为 -0 且 y 为 +0,则返回 true。
    6. 返回假。

(...)

+0 == -0顺便说一句,这同样适用。)

+0-0视为平等似乎是合乎逻辑的否则我们将不得不在我们的代码中考虑到这一点,而我个人不想这样做;)


笔记:

ES2015 引入了一种新的比较方法,Object.is. Object.is明确区分-0+0

Object.is(-0, +0); // false
实际上,这种行为模型限制了数学计算。例如,函数 1/x 在 0 中有一个无穷大的值,但是,如果我们接近 0,它与负侧的正数是分开的;前者的结果是+inf,后者的结果是-inf。
2021-03-11 00:57:51
确实1/0 === Infinity; // true1/-0 === -Infinity; // true
2021-03-14 00:57:51
所以我们有1 === 1并且+0 === -0但是1/+0 !== 1/-0多么奇怪!
2021-03-18 00:57:51
@FelixKling 或0 !== +0/ 0 !== -0,这确实也会产生问题!
2021-03-25 00:57:51
@Random:我认为它肯定比+0 !== -0;) 那确实会产生问题。
2021-04-08 00:57:51

我会将此添加为答案,因为我忽略了 @user113716 的评论。

您可以通过执行以下操作来测试 -0:

function isMinusZero(value) {
  return 1/value === -Infinity;
}

isMinusZero(0); // false
isMinusZero(-0); // true
@Chris,双精度指数的限制是e±308,您的数字只能以非规范化形式表示,并且不同的实现对于是否支持它们有不同的看法。关键是,在某些浮点模式的某些机器上,您的数字表示为,-0而在其他机器上则表示为非规范化数字0.000000000000001e-308这样的花车,真好玩
2021-03-22 00:57:51
这可能也适用于其他语言(我测试了 C 并且这有效)
2021-03-31 00:57:51
也应该检查 == 0,上面的 isMinusZero(-1e-323) 返回 true!
2021-04-05 00:57:51

我刚刚遇到一个例子,其中 +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。

谢谢。很奇怪添加零如何解决我遇到的问题。“如果所有其他方法都失败了,请加零。” 一生的教训。
2021-03-26 00:57:51
我刚刚在 Math.atan(y/x) 中也遇到了这个,它(也许令人惊讶)可以处理正或负无限的“y/x”,除了在 x 为 -0 的情况下它给出了错误的答案。用“(x+0)”替换“x”修复它。
2021-04-08 00:57:51

用于在 JavaScript 中表示 Number 类型IEEE 754 标准中,符号由一位表示(1 表示负数)。

因此,每个可表示的数字都存在负值和正值,包括0

这就是为什么-0和 都+0存在的原因。

是的,但在二进制补码中,负位也是值的一部分,所以一旦设置了负位,它就不再是零了。
2021-03-12 00:57:51
二进制补码也使用一位作为符号,但只有一个零(正)。
2021-03-16 00:57:51

回答原标题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 的正确符号。

您的函数返回trueor false,但不 返回-1and1
2021-03-24 00:57:51