通过ECMAScript 5.1 specification,+0
和-0
进行阅读。
为什么+0 === -0
会评估为true
?
答案 0 :(得分:165)
JavaScript使用IEEE 754 standard来表示数字。来自Wikipedia:
带有关联符号的有符号零为零。在普通算术中,-0 = + 0 = 0.但是,在计算中,某些数字表示允许存在两个零,通常用 -0(负零)和 +0表示(正零)。这发生在整数的一些有符号数表示中,并且在大多数浮点数表示中。数字0通常编码为+0,但可以用+0或-0表示。
用于浮点运算的IEEE 754标准(目前大多数支持浮点数的计算机和编程语言都使用)需要+0和-0。零可以被认为是扩展实数线的变体,使得1 / -0 =-∞和1 / + 0 = +∞,除以0仅对于±0 /±0和±∞/±∞未定义
本文包含有关不同表示形式的更多信息。
因此,从技术上讲,这就是必须区分零的原因。
但是,
+0 === -0
的计算结果为true。那是为什么(......)?
此行为在section 11.9.6中明确定义,严格的等式比较算法(重点部分是我的):
比较
x === y
,其中x
和y
是值,会产生 true 或 false 。这样的比较如下进行:(...)
如果Type(x)是Number,那么
- 如果x为NaN,则返回false。
- 如果y为NaN,则返回false。
- 如果x与y的数字值相同,则返回true。
- 如果x为+0且y为-0,则返回true。
- 如果x为-0且y为+0,则返回true。
- 返回false。
(...)
(同样适用于+0 == -0
btw。)
似乎逻辑上将+0
和-0
视为平等。否则我们必须在我们的代码中考虑到这一点,我个人不想这样做;)
注意:强>
ES2015引入了一种新的比较方法Object.is
。 Object.is
明确区分-0
和+0
:
Object.is(-0, +0); // false
答案 1 :(得分:15)
我将此作为答案添加,因为我忽略了@ user113716的评论。
您可以通过执行以下操作来测试-0:
function isMinusZero(value) {
return 1/value === -Infinity;
}
isMinusZero(0); // false
isMinusZero(-0); // true
答案 2 :(得分:3)
答案 3 :(得分:2)
有两个可能的值(位表示)为0.这不是唯一的。特别是在浮点数中,这可能发生。这是因为浮点数实际上存储为一种公式。
整数也可以以不同的方式存储。您可以使用带有附加符号位的数值,因此在16位空间中,您可以存储15位整数值和符号位。在此表示中,值1000(十六进制)和0000都是0,但其中一个是+0而另一个是-0。
这可以通过从整数值中减去1来避免,因此它的范围从-1到-2 ^ 16,但这样做会很不方便。
更常见的方法是将整数存储在“两个补码”中,但显然ECMAscript选择不这样做。在该方法中,数字范围从0000到7FFF为正。负数从FFFF(-1)到8000开始。
当然,同样的规则也适用于更大的整数,但我不希望我的F磨损。 ;)
答案 4 :(得分:2)
回答原始标题brainslugs83
:
Spudley
(在var sign = function(x) {
return 1 / x === 1 / Math.abs(x);
}
回答的评论中)指出了JS中+0和-0不相同的重要案例 - 实现为函数:
Math.sign
除了标准 let snapshotter = MKMapSnapshotter(options: options)
snapshotter.startWithCompletionHandler() {
snapshot, error in
if error != nil {
completion(image: nil, error: error)
return
}
let image = snapshot.image
let pin = MKPinAnnotationView(annotation: nil, reuseIdentifier: "") // I want to use custom annotation view instead of MKPinAnnotationView
let pinImage = UIImage(named: "pinImage")
UIGraphicsBeginImageContextWithOptions(image.size, true, image.scale);
image.drawAtPoint(CGPointMake(0, 0))
var homePoint = snapshot.pointForCoordinate(coordinates[0])
pinImage!.drawAtPoint(homePoint)
pinImage!.drawAtPoint(snapshot.pointForCoordinate(coordinates[1]))
let finalImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
completion(image: finalImage, error: nil)
}
之外,这将返回+0和-0的正确符号。
答案 5 :(得分:2)
我们可以使用Object.is
来区分+0和-0,还可以使用NaN==NaN
。
Object.is(+0,-0) //false
Object.is(NaN,NaN) //true
答案 6 :(得分:2)
+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
因此,只有 Object.is(+0, -0)
与其他的不同。
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
答案 7 :(得分:2)
如果您需要支持 sign
和 -0
的 +0
函数:
var sign = x => 1/x > 0 ? +1 : -1;
它充当 Math.sign
,除了 sign(0)
返回 1
和 sign(-0)
返回 -1
。
答案 8 :(得分:1)
答案 9 :(得分:0)
维基百科有一篇很好的文章来解释这种现象:http://en.wikipedia.org/wiki/Signed_zero
简而言之,+ 0和-0都是在IEEE浮点规范中定义的。它们在技术上与0不同,没有符号,这是一个整数,但在实践中它们都评估为零,因此可以忽略所有实际目的的区别。
答案 10 :(得分:0)
我刚刚遇到了一个示例,其中+0和-0的行为确实有很大不同:
N
请注意:即使对-0.0001之类的负数使用Math.round时,它实际上也将是-0,并且可能会破坏如上所示的一些后续计算。
快速而肮脏的方法可以解决此问题,例如:
Math.atan2(0, 0); //returns 0
Math.atan2(0, -0); //returns Pi
或者只是:
if (x==0) x=0;
在数字为-0的情况下,它将数字转换为+0。