我的一位同事偶然发现了一种方法来使用按位或者:
var a = 13.6 | 0; //a == 13
我们在谈论它并想知道一些事情。
Math.floor
有什么优势吗?也许它快一点? (双关语不打算)谢谢。
它是如何工作的?我们的理论是使用这样的运算符将数字转换为整数,从而删除小数部分
除了无符号右移>>>
之外的所有按位运算都适用于带符号的32位整数。因此,使用按位运算会将float转换为整数。
做Math.floor有什么优势吗?也许它快一点? (双关语不打算)
http://jsperf.com/or-vs-floor/2似乎稍快
它有任何缺点吗?也许它在某些情况下不起作用?清晰度是显而易见的,因为我们必须弄清楚,而且,我正在写这个问题。
Math.floor(NaN) === NaN
,而(NaN | 0) === 0
这是截断而不是地板。霍华德的回答是正确的;但我想补充一点,Math.floor
就负面数字做了它应该做的事情。在数学上,这就是一个楼层。
在上面描述的情况下,程序员对截断或完全关闭十进制更感兴趣。虽然,他们使用的语法有点模糊了他们将float转换为int的事实。
在ECMAScript 6中,相当于|0
的是Math.trunc,我应该说:
通过删除任何小数位数返回数字的整数部分。它只是截断点和它后面的数字,无论参数是正数还是负数。
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
你的第一点是正确的。该数字被转换为整数,因此删除任何十进制数字。请注意,Math.floor
向负无穷大舍入到下一个整数,因此在应用于负数时会产生不同的结果。
注意:删除指定的死链接
Javascript将Number
表示为Double Precision 64-bit Floating numbers。
Math.floor
考虑到了这一点。
按位运算在32位有符号整数中工作。 32位有符号整数使用第一位作为负号,另外31位是数字。因此,允许32位有符号数的最小和最大数分别为-2,147,483,648和2147483647(0x7FFFFFFFF)。
所以,当你在做| 0
时,你基本上就是在做& 0xFFFFFFFF
。这意味着,任何表示为0x80000000(2147483648)或更大的数字都将返回为负数。
例如:
// 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
。一旦你转到负数,Math.floor
向下舍入,而按位开始四舍五入。
正如我之前所说,Math.floor
更安全,因为它使用64位浮点运算。 Bitwise更快,是的,但仅限于32位签名范围。
总结一下:
0 to 2147483647
工作,Bitwise的工作方式相同。-2147483647 to 0
工作,Bitwise是1号码。-2147483648
且大于2147483647
的数字,Bitwise完全不同。如果你真的想调整性能并使用两者:
function floor(n) {
if (n >= 0 && n < 0x80000000) {
return n & 0xFFFFFFFF;
}
if (n > -0x80000000 && n < 0) {
return (n - 1) & 0xFFFFFFFF;
}
return Math.floor(n);
}
只是添加Math.trunc
像按位操作一样工作。所以你可以这样做:
function trunc(n) {
if (n > -0x80000000 && n < 0x80000000) {
return n & 0xFFFFFFFF;
}
return Math.trunc(n);
}