Number.sign() in javascript

Number.sign() in javascript

Wonder if there are any nontrivial ways of finding number’s sign (signum function)?
May be shorter / faster / more elegant solutions than the obvious one
var sign = number > 0 ? 1 : number < 0 ? -1 : 0; Short excerpt Use this and you'll be safe and fast function sign(x) { return typeof x === 'number' ? x ? x < 0 ? -1 : 1 : x === x ? 0 : NaN : NaN; } Results For now we have these solutions: 1. Obvious and fast function sign(x) { return x > 0 ? 1 : x < 0 ? -1 : 0; } 1.1. Modification from kbec - one type cast less, more performant, shorter [fastest] function sign(x) { return x ? x < 0 ? -1 : 1 : 0; } caution: sign("0") -> 1

2. Elegant, short, not so fast [slowest]
function sign(x) { return x && x / Math.abs(x); }

caution: sign(+-Infinity) -> NaN, sign(“0”) -> NaN
As of Infinity is a legal number in JS this solution doesn’t seem fully correct.

3. The art… but very slow [slowest]
function sign(x) { return (x > 0) – (x < 0); } 4. Using bit-shift fast, but sign(-Infinity) -> 0
function sign(x) { return (x >> 31) + (x > 0 ? 1 : 0); }

5. Type-safe [megafast]
! Seems like browsers (especially chrome’s v8) make some magic optimizations and this solution turns out to be much more performant than others, even than (1.1) despite it contains 2 extra operations and logically never can’t be faster.
function sign(x) {
return typeof x === ‘number’ ? x ? x < 0 ? -1 : 1 : x === x ? 0 : NaN : NaN; } Tools jsperf preformance tests; fiddle - type-cast tests; Improvements are welcome! [Offtopic] Accepted answer Andrey Tarantsov - +100 for the art, but sadly it is about 5 times slower than the obvious approach Frédéric Hamidi - somehow the most upvoted answer (for the time writing) and it's kinda cool, but it's definitely not how things should be done, imho. Also it doesn't correctly handle Infinity numbers, which are also numbers, you know. kbec - is an improvement of the obvious solution. Not that revolutionary, but taking all together I consider this approach the best. Vote for him 🙂

Solutions/Answers:

Solution 1:

More elegant version of fast solution:

var sign = number?number<0?-1:1:0

Solution 2:

Dividing the number by its absolute value also gives its sign. Using the short-circuiting logical AND operator allows us to special-case 0 so we don’t end up dividing by it:

var sign = number && number / Math.abs(number);

Solution 3:

The function you’re looking for is called signum, and the best way to implement it is:

function sgn(x) {
  return (x > 0) - (x < 0);
}

Solution 4:

Should this not support JavaScript’s (ECMAScript’s) signed zeroes? It seems to work when returning x rather than 0 in the “megafast” function:

function sign(x) {
    return typeof x === 'number' ? x ? x < 0 ? -1 : 1 : x === x ? x : NaN : NaN;
}

This makes it compatible with a draft of ECMAScript’s Math.sign (MDN):

Returns the sign of the x, indicating whether x is positive, negative or zero.

  • If x is NaN, the result is NaN.
  • 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.

Solution 5:

For people who are interested what is going on with latest browsers, in ES6 version there is a native Math.sign method. You can check the support here.

Basically it returns -1, 1, 0 or NaN

Math.sign(3);     //  1
Math.sign(-3);    // -1
Math.sign('-3');  // -1
Math.sign(0);     //  0
Math.sign(-0);    // -0
Math.sign(NaN);   // NaN
Math.sign('foo'); // NaN
Math.sign();      // NaN

Solution 6:

var sign = number >> 31 | -number >>> 31;

Superfast if you do not need Infinity and know that the number is an integer, found in openjdk-7 source: java.lang.Integer.signum()