javascript 中的 Number.sign()

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7624920/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 02:56:47  来源:igfitidea点击:

Number.sign() in javascript

javascriptalgorithmnumberssign

提问by disfated

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

想知道是否有任何重要的方法可以找到数字的符号(signum 函数)?
可能比显而易见的解决方案更短/更快/更优雅

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


Short answer!

简短的回答!

Use this and you'll be safe and fast (source: moz)

使用它,您将安全快速(来源:moz

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

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.Obvious and fast

1.明显快速

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


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

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

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

caution:sign("0") -> 1

警告:sign("0") -> 1



2.Elegant, short, not so fast [slowest]

2.优雅,简短,没那么快【最慢】

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

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

小心:sign(+-Infinity) -> NaNsign("0") -> NaN

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

作为InfinityJS 中的合法数字,此解决方案似乎并不完全正确。



3.The art... but very slow [slowest]

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

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


4.Using bit-shift
fast, but sign(-Infinity) -> 0

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

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


5.Type-safe [megafast]

5.类型安全[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.

似乎浏览器(尤其是 chrome 的 v8)进行了一些神奇的优化,结果证明这个解决方案比其他解决方案的性能要好得多,甚至比 (1.1) 还要好,尽管它包含 2 个额外的操作,而且逻辑上永远不会更快。

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


Tools

工具

Improvements are welcome!

欢迎改进!



[Offtopic] Accepted answer

[Offtopic] 接受的答案

  • 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 :)

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

  • Frédéric Hamidi- 不知何故,这是最受好评的答案(在写作时间),它有点酷,但这绝对不是应该如何做的,恕我直言。它也不能正确处理无穷大数字,你知道,它们也是数字。

  • kbec- 是对明显解决方案的改进。不是革命性的,但综合起来,我认为这种方法是最好的。为他投票:)

采纳答案by kbec

More elegant version of fast solution:

更优雅的快速解决方案:

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

回答by Frédéric Hamidi

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

将数字除以其绝对值也给出了它的符号。使用短路逻辑 AND 运算符允许我们进行特殊处理,0因此我们最终不会除以它:

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

回答by Andrey Tarantsov

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

您正在寻找的函数称为signum,实现它的最佳方法是:

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

回答by Martijn

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

这不应该支持 JavaScript (ECMAScript) 的带符号零吗?在“megafast”函数中返回 x 而不是 0 时似乎有效:

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):

这使它与ECMAScript 的 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.

返回 x 的符号,指示 x 是正数、负数还是零。

  • 如果 x 为 NaN,则结果为 NaN。
  • 如果 x 是?0,则结果是?0。
  • 如果 x 为 +0,则结果为 +0。
  • 如果 x 为负且不是 ?0,则结果为 ?1。
  • 如果 x 为正数且不为 +0,则结果为 +1。

回答by Salvador Dali

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

对于那些对最新浏览器正在发生的事情感兴趣的人,在 ES6 版本中有一个原生的Math.sign方法。您可以在此处查看支持

Basically it returns -1, 1, 0or NaN

基本上它返回-1, 1,0NaN

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

回答by Toxiro

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()

如果您不需要 Infinity 并且知道该数字是一个整数,则可以在 openjdk-7 源中找到: java.lang.Integer.signum()

回答by jaya

I thought I'd add this just for fun:

我想我会添加这个只是为了好玩:

function sgn(x){
  return 2*(x>0)-1;
}

0 and NaN will return -1
works fine on +/-Infinity

0 和 NaN 将返回 -1
在 +/-Infinity 上工作正常

回答by Andy Ray

A solution that works on all numbers, as well as 0and -0, as well as Infinityand -Infinity, is:

一个解决方案,对所有的数字作品,以及0-0,以及Infinity-Infinity是:

function sign( number ) {
    return 1 / number > 0 ? 1 : -1;
}

See the question "Are +0 and -0 the same?" for more information.

有关更多信息,请参阅问题“ +0 和 -0 是否相同?”。



Warning:None of these answers, including the now standard Math.signwill work on the case 0vs -0. This may not be an issue for you, but in certain physics implementations it may matter.

警告:这些答案,包括 now 标准都不Math.sign适用于 case 0vs -0. 这对您来说可能不是问题,但在某些物理实现中可能很重要。

回答by Alexander Shutau

I don't see any practical sence of returning -0 and 0 from Math.signso my version is:

我没有看到返回 -0 和 0 的任何实际意义,Math.sign所以我的版本是:

function sign(x) {
    x = Number(x);
    if (isNaN(x)) {
        return NaN;
    }
    if (x === -Infinity || 1 / x < 0) {
        return -1;
    }
    return 1;
};

sign(100);   //  1
sign(-100);  // -1
sign(0);     //  1
sign(-0);    // -1

回答by James Wilkins

The methods I know of are as follows:

我知道的方法如下:

Math.sign(n)

数学符号(n)

var s = Math.sign(n)

var s = Math.sign(n)

This is the native function, but is slowest of all because of the overhead of a function call. It does however handle 'NaN' where the others below may just assume 0 (i.e. Math.sign('abc') is NaN).

这是本机函数,但由于函数调用的开销,它是最慢的。然而,它确实处理 'NaN',其中下面的其他人可能只是假设 0(即 Math.sign('abc') 是 NaN)。

((n>0) - (n<0))

((n>0) - (n<0))

var s = ((n>0) - (n<0));

var s = ((n>0) - (n<0));

In this case only the left or right side can be a 1 based on the sign. This results in either 1-0(1), 0-1(-1), or 0-0(0).

在这种情况下,只有左侧或右侧可以是基于符号的 1。这将导致1-0(1)、0-1(-1) 或0-0(0)。

The speed of this one seems neck and neck with the next one below in Chrome.

在 Chrome 中,这个速度与下面的下一个速度似乎并驾齐驱。

(n>>31)|(!!n)

(n>>31)|(!!n)

var s = (n>>31)|(!!n);

var s = (n>>31)|(!!n);

Uses the "Sign-propagating right shift". Basically shifting by 31 drops all bits except the sign. If the sign was set, this results in -1, otherwise it is 0. Right of |it tests for positive by converting the value to boolean (0 or 1 [BTW: non-numeric strings, like !!'abc', become 0 in this case, and not NaN]) then uses a bitwise OR operation to combine the bits.

使用“符号传播右移”。基本上移位 31 会丢弃除符号之外的所有位。如果设置了符号,则结果为 -1,否则为 0。|通过将值转换为布尔值(0 或 1 [BTW:非数字字符串,如!!'abc',在这种情况下变为 0,并且not NaN]) 然后使用按位或运算来组合这些位。

This seems the best averageperformance across the browsers (best in Chrome and Firefox at least), but not the fastest in ALL of them. For some reason, the ternary operator is faster in IE.

这似乎是所有浏览器中最好的平均性能(至少在 Chrome 和 Firefox 中是最好的),但并不是所有浏览器中最快的。出于某种原因,三元运算符在 IE 中更快。

n?n<0?-1:1:0

n?n<0?-1:1:0

var s = n?n<0?-1:1:0;

var s = n?n<0?-1:1:0;

Fastest in IE for some reason.

出于某种原因,在 IE 中速度最快。

jsPerf

jsPerf

Tests performed: https://jsperf.com/get-sign-from-value

执行的测试:https: //jsperf.com/get-sign-from-value