+0和-0是否相同?

Ran*_*lue 163 javascript

阅读ECMAScript 5.1规范,+0-0进行区分.

为什么然后+0 === -0评估true

Fel*_*ing 182

JavaScript使用IEEE 754标准来表示数字.来自维基百科:

带符号的零为零,带有相关符号.在普通算术中,-0 = + 0 = 0.然而,在计算中,一些数字表示允许存在两个零,通常用-0(负零)+0(正零)表示.这发生在整数的一些有符号数表示中,并且在大多数浮点数表示中.数字0通常编码为+0,但可以用+0或-0表示.

用于浮点运算的IEEE 754标准(目前大多数计算机和支持浮点数的编程语言使用)都需要+0和-0.零可以被认为是扩展实数线的变体,使得1/-0 =-∞和1/+ 0 = +∞,除以0仅对于±0 /±0和±∞/±∞未定义.

本文包含有关不同表示的更多信息.

所以这就是为什么技术上必须区分零.

但是,+0 === -0评估结果为true.这是为什么 (...) ?

此行为在第11.9.6节中明确定义,严格的等式比较算法(部分重点是我的):

比较x === y,其中xy是值,产生.这样的比较如下进行:

(......)

  • 如果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. 返回false.

(......)

(同样适用于+0 == -0顺便说一句.)

从逻辑上讲,待遇+0-0平等.否则我们必须在我们的代码中考虑到这一点,我个人不想这样做;)


注意:

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

Object.is(-0, +0); // false
Run Code Online (Sandbox Code Playgroud)

  • 所以我们有`1 === 1`和`+0 === -0`但是`1/+ 0!== 1/-0`.多奇怪啊! (46认同)
  • 确实`1/0 ===无限; // true`和`1/-0 === -Infinity; //真. (13认同)
  • @Random:我认为它肯定比`+0!== -0`更好;)这可能会造成问题. (8认同)
  • 实际上,这种行为模型限制了数学计算.例如,函数1/x在0中具有无穷大的值,但是如果我们从负侧的正值接近0则它被分开; 在前者中,结果是+ inf,在后者中,-inf. (3认同)

lak*_*tak 17

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

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

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

isMinusZero(0); // false
isMinusZero(-0); // true
Run Code Online (Sandbox Code Playgroud)

  • 应该检查== 0也是如此,上面的isMinusZero(-1e-323)返回true! (6认同)
  • @Chris,双精度指数的限制是“e±308”,您的数字只能以非规范化形式表示,并且不同的实现对于在哪里支持它们有不同的意见。关键是,在某些浮点模式的机器上,您的数字表示为“-0”,而在其他机器上则表示为非规范化数字“0.000000000000001e-308”。这样的浮游,真好玩 (2认同)

Ngu*_*ong 9

2021 年的答案

\n
\n

+0和-0一样吗?

\n
\n

简短的回答:取决于您使用的比较运算符。

\n

长答案:

\n

基本上,到目前为止我们已经有4 种比较类型:

\n
    \n
  1. \xe2\x80\x98loose\xe2\x80\x99相等
  2. \n
\n
console.log(+0 == -0); // true\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. \xe2\x80\x98strict\xe2\x80\x99相等
  2. \n
\n
console.log(+0 === -0); // true\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. \xe2\x80\x98相同值\xe2\x80\x99相等( ES2015\'sObject.is )
  2. \n
\n
console.log(Object.is(+0, -0)); // false\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. \xe2\x80\x98同值零\xe2\x80\x99相等 ES2016
  2. \n
\n
console.log([+0].includes(-0)); // true\n
Run Code Online (Sandbox Code Playgroud)\n

结果,只是Object.is(+0, -0)与其他的有所不同。\n

\r\n
\r\n
console.log(+0 == -0); // true\n
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n

在此输入图像描述

\n


Arn*_*anc 6

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

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

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

  • 二进制补码也使用一位作为符号,但只有一个零(正)。 (3认同)
  • 是的,但在二进制补码中,负位也是值的一部分,所以一旦设置了负位,它就不再是零了。 (2认同)

Fox*_*ode 6

我刚刚遇到了一个示例,其中+0和-0的行为确实有很大不同:

Math.atan2(0, 0);  //returns 0
Math.atan2(0, -0); //returns Pi
Run Code Online (Sandbox Code Playgroud)

请注意:即使对-0.0001之类的负数使用Math.round时,它实际上也会是-0,并且可能会破坏如上所示的一些后续计算。

解决此问题的快速而肮脏的方法是做类似的事情:

if (x==0) x=0;
Run Code Online (Sandbox Code Playgroud)

要不就:

x+=0;
Run Code Online (Sandbox Code Playgroud)

如果它是-0,则会将数字转换为+0。

  • 谢谢。很奇怪,添加零如何解决我遇到的问题。“如果一切都失败了,就加零。” 一生的教训。 (2认同)