Using bitwise OR 0 to floor a number
我的一位同事偶然发现了一种方法,可以使用按位或:
1 | var a = 13.6 | 0; //a == 13 |
我们在谈论它,想知道一些事情。
- 它是如何工作的?我们的理论是,使用这样的运算符将数字强制转换为整数,从而删除小数部分。
- 它与执行
Math.floor 相比有什么优势吗?也许快一点?(双关语不是有意的) - 它有什么缺点吗?也许在某些情况下不起作用?明晰是显而易见的,因为我们必须弄清楚,好吧,我在写这个问题。
谢谢。
How does it work? Our theory was that using such an operator casts the
number to an integer, thus removing the fractional part
除无符号右移(
Does it have any advantages over doing Math.floor? Maybe it's a bit
faster? (pun not intended)
http://jspef.com/or-vs-floor/2似乎稍微快一点
Does it have any disadvantages? Maybe it doesn't work in some cases?
Clarity is an obvious one, since we had to figure it out, and well,
I'm writting this question.
- 不会通过jslint。
- 仅限32位有符号整数
- 奇怪的比较行为:
Math.floor(NaN) === NaN ,而(NaN | 0) === 0 。
这是相对于地板的截断。霍华德的回答有点正确,但我想补充一点,
在上面描述的情况下,程序员更感兴趣的是截断或切掉小数。不过,它们使用的语法有点掩盖了一个事实,即它们正在将浮点转换为int。
在ecmascript 6中,与
Returns the integral part of a number by removing any fractional digits. It just truncate the dot and the digits behind it, no matter whether the argument is a positive number or a negative number.
1 2 3 4 5 6 7 8 | Math.trunc(13.37) // 13 Math.trunc(42.84) // 42 Math.trunc(0.123) // 0 Math.trunc(-0.123) // -0 Math.trunc("-1.123")// -1 Math.trunc(NaN) // NaN Math.trunc("foo") // NaN Math.trunc() // NaN |
你的第一点是正确的。数字被转换为整数,因此任何十进制数字都将被删除。请注意,
规范说它被转换为整数:
Let lnum be ToInt32(lval).
性能:这之前已经在JSPERF中进行过测试。
注:已删除规范的死链接
javascript将
位操作在32位有符号整数中工作。32位有符号整数使用第一位作为负的能指,其他31位是数字。因此,允许的最小和最大32位有符号数字分别为-2147483648和2147483647(0x7ffffff)。
所以当你在做
例如:
1 2 3 4 5 6 7 8 9 10 11 | // Safe (2147483647.5918 & 0xFFFFFFFF) === 2147483647 (2147483647 & 0xFFFFFFFF) === 2147483647 (200.59082098 & 0xFFFFFFFF) === 200 (0X7FFFFFFF & 0xFFFFFFFF) === 0X7FFFFFFF // Unsafe (2147483648 & 0xFFFFFFFF) === -2147483648 (-2147483649 & 0xFFFFFFFF) === 2147483647 (0x80000000 & 0xFFFFFFFF) === -2147483648 (3000000000.5 & 0xFFFFFFFF) === -1294967296 |
也。按位运算不"楼层"。它们截短,这与前面所说的一样,它们最接近于
正如我之前所说,
总结:
- 如果你是从
0 to 2147483647 开始工作,那么按位工作也是一样的。 - 如果您从
-2147483647 to 0 工作,则位为1。 - 对于小于
-2147483648 和大于2147483647 的数字,按位完全不同。
如果您真的想调整性能并同时使用这两者:
1 2 3 4 5 6 7 8 9 | function floor(n) { if (n >= 0 && n < 0x80000000) { return n & 0xFFFFFFFF; } if (n > -0x80000000 && n < 0) { return (n - 1) & 0xFFFFFFFF; } return Math.floor(n); } |
只需添加
1 2 3 4 5 6 | function trunc(n) { if (n > -0x80000000 && n < 0x80000000) { return n & 0xFFFFFFFF; } return Math.trunc(n); } |