Javascript 使用按位或 0 对数字求底
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7487977/
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
Using bitwise OR 0 to floor a number
提问by Alex Turpin
A colleague of mine stumbled upon a method to floor float numbers using a bitwise or:
我的一位同事偶然发现了一种使用按位或来计算浮点数的方法:
var a = 13.6 | 0; //a == 13
We were talking about it and wondering a few things.
我们正在谈论它并想知道一些事情。
- 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) - 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.
- 它是如何工作的?我们的理论是,使用这样的运算符将数字强制转换为整数,从而去除小数部分
- 它比做有什么优势
Math.floor
吗?也许它会快一点?(双关语不是故意的) - 它有什么缺点吗?也许它在某些情况下不起作用?清晰度是显而易见的,因为我们必须弄清楚,好吧,我正在写这个问题。
Thanks.
谢谢。
采纳答案by Joe
How does it work? Our theory was that using such an operator casts the number to an integer, thus removing the fractional part
它是如何工作的?我们的理论是,使用这样的运算符将数字强制转换为整数,从而去除小数部分
All bitwise operations except unsigned right shift, >>>
, work on signed 32-bit integers. So using bitwise operations will convert a float to an integer.
除无符号右移之外的所有按位运算都>>>
适用于有符号的 32 位整数。因此,使用按位运算会将浮点数转换为整数。
Does it have any advantages over doing Math.floor? Maybe it's a bit faster? (pun not intended)
它比做 Math.floor 有什么优势吗?也许它会快一点?(双关语不是故意的)
http://jsperf.com/or-vs-floor/2seems slightly faster
http://jsperf.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.
它有什么缺点吗?也许它在某些情况下不起作用?清晰度是显而易见的,因为我们必须弄清楚,好吧,我正在写这个问题。
- Will not pass jsLint.
- 32-bit signed integers only
- Odd Comparative behavior:
Math.floor(NaN) === NaN
, while(NaN | 0) === 0
- 不会通过 jsLint。
- 仅限 32 位有符号整数
- 奇怪的比较行为:
Math.floor(NaN) === NaN
, 而(NaN | 0) === 0
回答by Chad La Guardia
This is truncationas opposed to flooring. Howard's answer is sort of correct; But I would add that Math.floor
does exactly what it is supposed to with respect to negative numbers. Mathematically, that is what a floor is.
这是截断而不是地板。霍华德的回答有点正确;但我想补充一点,Math.floor
它完全符合负数的预期。从数学上讲,这就是地板。
In the case you described above, the programmer was more interested in truncationor chopping the decimal completely off. Although, the syntax they used sort of obscures the fact that they are converting the float to an int.
在上面描述的情况下,程序员更感兴趣的是截断或完全切掉小数点。虽然,他们使用的语法有点掩盖了他们将浮点数转换为 int 的事实。
回答by zangw
In ECMAScript 6, the equivalent of |0
is Math.trunc, kind of I should say:
在ECMAScript中6,相当于|0
是Math.trunc,善良的我应该说:
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.
通过删除任何小数位返回数字的整数部分。它只是截断点及其后面的数字,无论参数是正数还是负数。
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
回答by Howard
Your first point is correct. The number is cast to an integer and thus any decimal digits are removed. Please note, that Math.floor
rounds to the next integer towards minus infinity and thus gives a different result when applied to negative numbers.
你的第一点是正确的。该数字被转换为整数,因此任何十进制数字都将被删除。请注意,它Math.floor
向负无穷大方向舍入到下一个整数,因此在应用于负数时会产生不同的结果。
回答by pimvdb
回答by ShortFuse
Javascript represents Number
as Double Precision 64-bit Floating numbers.
Javascript 表示Number
为双精度 64 位浮点数。
Math.floor
works with this in mind.
Math.floor
考虑到这一点。
Bitwise operations work in 32bit signedintegers. 32bit signed integers use first bit as negative signifier and the other 31 bits are the number. Because of this, the min and max number allowed 32bit signed numbers are -2,147,483,648 and 2147483647 (0x7FFFFFFFF), respectively.
按位运算适用于 32 位有符号整数。32 位有符号整数使用第一位作为负号,其他 31 位是数字。因此,允许的 32 位有符号数的最小值和最大值分别为 -2,147,483,648 和 2147483647 (0x7FFFFFFFF)。
So when you're doing | 0
, you're essentially doing is & 0xFFFFFFFF
. This means, any number that is represented as 0x80000000 (2147483648) or greater will return as a negative number.
因此,当您在做 时| 0
,您实际上是在做的是& 0xFFFFFFFF
。这意味着,任何表示为 0x80000000 (2147483648) 或更大的数字都将返回为负数。
For example:
例如:
// 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
Also. Bitwise operations don't "floor". They truncate, which is the same as saying, they round closest to 0
. Once you go around to negative numbers, Math.floor
rounds downwhile bitwise start rounding up.
还。按位运算不“地板”。它们截断,这就是说,它们最接近0
。一旦你到处去负数,Math.floor
几轮下来,而按位开始舍去了。
As I said before, Math.floor
is safer because it operates with 64bit floating numbers. Bitwise is faster, yes, but limited to 32bit signed scope.
正如我之前所说,Math.floor
更安全,因为它使用 64 位浮点数运行。按位更快,是的,但仅限于 32 位有符号范围。
To summarize:
总结一下:
- Bitwise works the same if you work from
0 to 2147483647
. - Bitwise is 1 number off if you work from
-2147483647 to 0
. - Bitwise is completely different for numbers less than
-2147483648
and greater than2147483647
.
- 如果您从
0 to 2147483647
. - 如果您从
-2147483647 to 0
. - 对于小于
-2147483648
和大于 的数字,按位完全不同2147483647
。
If you reallywant to tweak performance and use both:
如果您真的想调整性能并同时使用两者:
function floor(n) {
if (n >= 0 && n < 0x80000000) {
return n & 0xFFFFFFFF;
}
if (n > -0x80000000 && n < 0) {
return (n - 1) & 0xFFFFFFFF;
}
return Math.floor(n);
}
Just to add Math.trunc
works like bitwise operations. So you can do this:
只是添加Math.trunc
像按位操作一样的工作。所以你可以这样做:
function trunc(n) {
if (n > -0x80000000 && n < 0x80000000) {
return n & 0xFFFFFFFF;
}
return Math.trunc(n);
}