IEEE 754 has a precise meaning for sign bit. JavaScript’s Math.sign
falls
short on -0.0
and +0.0
. This is a shortcoming of a "batteries included"
approach to language design.
Correctly obtaining the sign bit of a Number in JavaScript is somewhat
unintuitive: the naïve x < 0
approach fails if x
is -0.0
because 0.0
and -0.0
compare equal to each other.
One can instead rely on division by zero returning one of -Infinity
or +Infinity
: 1.0 / x < 0
. This now has the interesting caveat of returning NaN
if x
was NaN
. It’s also highly counter-intuitive.
JavaScript aficionado will know that Object.is(-0, x)
will return true
when x
is -0
but not when it’s 0
. This is surprising for developers who are
more numerics-oriented than object-—dare I say prototype-?—oriented. These
developers just want the sign bit, IEEE 754 has a very precise definition of
what the sign bit is, and why can’t JavaScript just give them the sign bit?
This issue has been discussed previously but was never addressed. We believe that this proposal can fix this oft-encountered problem once and for all.
1. Revision History
-
Presented at the 2017-01 TC39 meeting and moved to Stage 1.
2. Background
2.1. IEEE 754
[IEEE754] section 5.5.1 defines sign bit operations. These operations are quiet-computational operations which only affect the sign bit of the arithmetic format. The operations treat floating-point numbers and NaNs alike, and signal no exception. As defined, they may propagate non-canonical encodings.
The following operations are defined:
-
copy
-
negate
-
abs
2.2. C / C++
[C] and [Cpp] define signbit
in <math.h>
and <cmath>
respectively. It
returns a nonzero int
value if and only if the sign of its argument value is
negative. The signbit
macro reports the sign of all values, including
infinities, zeros, and NaNs.
2.3. Go
[Go]'s math package defines Signbit
as true
if x
is negative or negative
zero. While the specification is silent on NaN, the implementation clearly extracts the
sign bit regardless of NaN-ness.
2.4. Math.sign
JavaScript provides Math.sign
which is specified as follows:
Returns the sign of the x, indicating whether x is positive, negative or zero.
If
x
isNaN
, the result isNaN
.If
x
is-0
, the result is-0
.If
x
is+0
, the result is+0
.If
x
is negative and not-0
, the result is-1
.If
x
is positive and not+0
, the result is+1
.
This falls short when dealing with -0
and +0
since these values both compare
equal.
3. Proposal
Given existing precedent as well as common hardware support, we propose adding Math.signbit
to JavaScript as follows.
3.1. Math.signbit(x)
Returns whether the sign bit of x
is set.
-
If
n
isNaN
, the result isfalse
. -
If
n
is-0
, the result istrue
. -
If
n
is negative, the result istrue
. -
Otherwise, the result is
false
.
Note: The "Function Properties of the Math Object" section already states:
"Each of the following Math
object functions applies the ToNumber
abstract
operation to each of its argument."
3.2. Alternatives
This proposal makes decisions which TC39 may want to consider modifying:
-
Coercison
ToNumber
. -
The return type is Boolean.
-
NaN is equivalent to a positive number.