42

It turns out +0 === -0 evaluates to true despite +0 and −0 being different entities. So, how do you differentiate +0 from −0?

There is a hack:

if (1 / myZero > 0) {
   // myZero is +0
} else {
   // myZero is -0
}

Can I do better?

user3840170
  • 26,597
  • 4
  • 30
  • 62
Randomblue
  • 112,777
  • 145
  • 353
  • 547
  • 17
    Why do you need to know this? (Not condescending... I am really curious!) – Jason Gennaro Aug 28 '11 at 20:35
  • 2
    your solution seems reasonable. (+0 === -0) being true seems like an oversight in the language so I don't know how else you'll resolve it. I wouldn't expect it to come up frequently. – evan Aug 28 '11 at 20:35
  • 12
    @evan, it's not an oversight, it's what IEEE 754 requires. – John Flatness Aug 28 '11 at 20:42
  • 2
    You don't need a function, just do this check: `if ( 1 / x > 0 ) { ...` – Šime Vidas Aug 28 '11 at 20:44
  • 5
    @Jason: I'm just playing around with the specs, and considering a bunch of thought experiments. These kind of bizarre things could potentially lead to difficult-to-find bugs. See one of my fears here: http://stackoverflow.com/questions/7223517/function-given-strictly-equal-arguments-yielding-non-strictly-equal-results – Randomblue Aug 28 '11 at 21:02
  • @JasonGennaro - right now I'm writing my own `printf` in javascript and `%+f` specifier must distinguish between `+0` and `-0` – csharpfolk Aug 07 '15 at 17:02

9 Answers9

27

In ECMAScript 6 Object.is behaves like === except that it distinguishes positive and negative zeroes, and Object.is(NaN, NaN) evaluates to true. (See here for a writeup.)

Chrome 24 supports Object.is.

Randomblue
  • 112,777
  • 145
  • 353
  • 547
  • there's also an alternative version for ECMAScript 5 at the end of [this documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) if you need it for old browsers – Gerard Brull Aug 16 '16 at 01:43
14

This is still some kind of hack, but a look at the specs suggests this:

Math.atan2(0, -0) === Math.PI // true
Math.atan2(0,  0) === 0       // true
pimvdb
  • 151,816
  • 78
  • 307
  • 352
9

According to David Flanagan's book, p. 34, dividing 1 by your zero will produce the corresponding infinity, which can then be used in an equality check:

1 / 0
> Infinity
1 / -0
> -Infinity

And here's the behavior of the equality comparisons of infinities:

Infinity === -Infinity
> false
Infinity === Infinity
> true
-Infinity === Infinity
> false
-Infinity === -Infinity
> true
Matt Fenwick
  • 48,199
  • 22
  • 128
  • 192
4

To check the negative zero, here is one simple solution.

function isNegativeZero(n) {
    n = Number( n );
    return (n === 0) && (1 / n === -Infinity);
}
zangw
  • 43,869
  • 19
  • 177
  • 214
3

As people seem stumped as to what the practical need for this would be: here is my use case...

I needed a solution to sort the columns of a table by their index. Click the <th> and invoke the sorter with [ordinal] for ascending and -[ordinal] for descending. The first column would give -0 for descending or 0 for ascending.

So I need to differentiate between +0 and -0 and ended up here. The solution that worked for me is in the comment by @Šime Vidas, but is hidden away somewhat.

// This comparison works for all negatives including -0
if ( 1 / x > 0 ) { }

1 / -0 > 0  // false
1 / 0 > 0  // true
1 / -99 > 0 // false
1 / 99 > 0 // true

// WRONG: this naive comparison might give unexpected results
if ( x > 0 ) { }

-0 > 0 // true
// Gotcha
blackgreen
  • 34,072
  • 23
  • 111
  • 129
Roy Prins
  • 2,790
  • 2
  • 28
  • 47
3

This returns +0:

-0 + 0

This doesn't help to differenciate -0 and +0, but this helps in ensuring that some value is not -0.

1 / -0       => -Infinity  
1 / (-0 + 0) => Infinity
Arnaud Le Blanc
  • 98,321
  • 23
  • 206
  • 194
1

One straight option in Node.js is to use Buffer.

var negZero = Buffer('8000000000000000', 'hex')

var buf = Buffer(8);
buf.writeDoubleBE(myZero);

if (buf.equals(negZero)) {
    // myZero is -0
} else {
    // myZero is +0
}

Also, you can easily browserify them by buffer module.

hakatashi
  • 9,006
  • 2
  • 22
  • 22
  • 1
    Same idea by using TypedArray: `isPosZero = x => !(new Uint8Array(new Float64Array([x]).buffer).some(Boolean))` – tsh Jan 09 '18 at 07:37
0

As hinted at by Matt Fenwick, you could just do (using the var zero):

if(1/zero===Infinity) {
  // zero is +0
} else {
  // zero is -0
}
user31415
  • 446
  • 7
  • 16
0

Use Math.sign()

console.log(Math.sign( 1 / +0 ));
console.log(Math.sign( 1 / -0 ));
Sean Morris
  • 384
  • 2
  • 9