Number.sign()在JavaScript中

不知道是否有任何不寻常的方法find号码的符号( signum函数 )?
可能比明显的更短/更快/更优雅的解决scheme

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

简短的摘录

使用这个,你会安全和快速

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

结果

现在我们有这些解决scheme:


1.明显而快速

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

1.1。 从kbec的修改 – 一个types更less,更高性能,更短[最快]

 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) -> NaNsign("0") -> NaN

至于Infinity是JS中的一个合法的数字,这个解决scheme似乎并不完全正确。


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

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

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

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

5.types安全[megafast]

看起来像浏览器(特别是chrome的v8)做了一些神奇的优化,这个解决scheme比其他的更好,甚至比(1.1)更多,尽pipe它包含了2个额外的操作,逻辑上从来不会更快。

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

工具

  • jsperf性能testing;
  • 小提琴式的testing;

改进是值得欢迎的!


[Offotic]接受的答案

  • 安德烈·塔兰托夫 ( Andrey Tarantov) – 为艺术增加了 100分,但令人遗憾的是,这比明显的方法慢了5倍

  • 弗雷德里克·哈米迪 ( FrédéricHamidi) – 不知何故是最有争议的答案(写作的时候),这有点酷,但绝对不是应该怎么做,恕我直言。 此外,它不能正确处理无限数字,这也是数字,你知道。

  • Kbec – 是一个显而易见的解决scheme的改进。 不是那么革命,而是把所有的东西都放在一起,我认为这种方法是最好的 为他投票:)

更优雅的快速解决scheme版本:

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

数字除以其绝对值也给出了它的符号。 使用短路逻辑AND运算符允许我们使用特殊情况0所以我们不会被最终分割:

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

你正在寻找的函数叫做signum ,实现它的最好方法是:

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

如果这不支持JavaScript的(ECMAScript)签名为零? 它在“megafast”函数中返回x而不是0时似乎工作:

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

这使得它与ECMAScript的Math.sign ( MDN )的草稿兼容:

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

  • 如果x是NaN,那么结果是NaN。
  • 如果x是-0,结果是-0。
  • 如果x是+0,结果是+0。
  • 如果x是负数而不是-0,则结果是-1。
  • 如果x是正值而不是+0,结果是+1。

对于那些对最新浏览器感兴趣的用户来说,在ES6版本中有一个原生的Math.sign方法。 你可以在这里查看支持 。

基本上它返回-1NaN

 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 
 var sign = number >> 31 | -number >>> 31; 

超快,如果你不需要无穷大,并知道这个数字是一个整数,在openjdk-7源: java.lang.Integer.signum()

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

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

0和NaN将返回-1
在+/- Infinity上运行良好

一个适用于所有数字以及0-0以及Infinity-Infinity的解决scheme是:

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

看到问题“ 是+0和-0是否相同? ”了解更多信息。


警告:这些答案都没有,包括现在的标准Math.sign将在案例0 vs -0上起作用。 这对你来说可能不是问题,但是在某些物理实现中它可能很重要。

你可以移位数字并检查最高有效位(MSB)。 如果MSB是1,那么这个数字是负数。 如果它是0,那么数字是正数(或0)。

我只是想问同样的问题,但在我写完之前find了一个解决scheme,看到这个问题已经存在了,但是没有看到这个解决scheme。

(n >> 31) + (n > 0)

(n >> 31) + (n>0?1:0)join三元组似乎更快

非常类似Martijn的答案

 function sgn(x) { isNaN(x) ? NaN : (x === 0 ? x : (x < 0 ? -1 : 1)); } 

我觉得它更可读。 另外(或者,根据你的观点,但是),它也可以解释为一个数字的东西, 例如,当呈现'-5'时它返回-1

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

 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 

我所知道的方法如下:

Math.sign(N)

var s = Math.sign(n)

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

((n> 0) – (n <0))

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

在这种情况下,只有左侧或右侧可以是1的标志。 这导致1-0 (1), 0-1 (-1)或0-0 (0)。

Chrome浏览器的速度似乎与下面的一个不相上下。

(N >> 31)|(!n)的

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

使用“签名传播右移”。 除了符号之外,基本上移动了31位。 如果符号已设置,则结果为-1,否则为0.右侧| 它通过将值转换为布尔值(0或1 [BTW:非数字string,如!!'abc' ,在这种情况下变成0,而不是NaN])来testing正数,然后使用按位“或”运算来合并比特。

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

N N <0 -1:?1:0

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

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

jsPerf

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