JavaScript 中的 Number.sign()

2022-01-17 00:00:00 algorithm numbers sign 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;

<小时>

简答!

使用它,你会安全又快速(来源:moz)

if (!Math.sign) Math.sign = function(x) { return ((x > 0) - (x < 0)) || +x; };

您可能想查看性能和类型强制比较 fiddle

You may want to look at performance and type-coercing comparison fiddle

很久过去了.进一步主要是出于历史原因.

Long time has passed. Further is mainly for historical reasons.

<小时>

结果

目前我们有以下解决方案:


Results

For now we have these solutions:

1. 明显且快速

function sign(x) { return x > 0 ? 1 : x < 0 ? -1 : 0; }

<小时>

1.1. 修改自 kbec - 一种类型转换更少,性能更高,更短[最快]


1.1. Modification from kbec - one type cast less, more performant, shorter [fastest]

function sign(x) { return x ? x < 0 ? -1 : 1 : 0; }

注意: sign("0") ->1

2.优雅,短,不那么快[最慢]

function sign(x) { return x && x / Math.abs(x); }

注意: sign(+-Infinity) ->NaN, sign("0") ->NaN

Infinity 是 JS 中的合法数字,此解决方案似乎并不完全正确.

As of Infinity is a legal number in JS this solution doesn't seem fully correct.

3.艺术...但很慢[最慢]

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

<小时>

4.使用位移
快,但是 sign(-Infinity) ->0

function sign(x) { return (x >> 31) + (x > 0 ? 1 : 0); }

<小时>

5. 类型安全 [megafast]

! 似乎浏览器(尤其是 chrome 的 v8)做了一些神奇的优化,结果证明这个解决方案比其他解决方案性能更高,甚至比 (1.1) 尽管它包含 2 个额外的操作并且逻辑上从来没有再快不过了.

! 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;
}

<小时>

工具

  • jsperf 性能测试;
  • fiddle - 类型转换测试;

  • Tools

    • jsperf preformance tests;
    • fiddle - type-cast tests;
    • 欢迎改进!

      • Andrey Tarantsov - 艺术+100,但遗憾的是它比明显的方法慢了大约 5 倍

      • Andrey Tarantsov - +100 for the art, but sadly it is about 5 times slower than the obvious approach

      Frédéric Hamidi - 不知何故是最受好评的答案(就写作时间而言),它有点酷,但绝对不是事情应该是的样子完成,恕我直言.它也不能正确处理无穷大数,你知道,它们也是数字.

      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 - 是对明显解决方案的改进.不是革命性的,但综合起来,我认为这种方法是最好的.投票给他:)

      kbec - is an improvement of the obvious solution. Not that revolutionary, but taking all together I consider this approach the best. Vote for him :)

      推荐答案

      更优雅版的快速解决方案:

      More elegant version of fast solution:

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

相关文章