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) -> NaN
, sign("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方法。 你可以在这里查看支持 。
基本上它返回-1
或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
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