it-swarm.cn

使用按位 OR 一个数字

我的一位同事偶然发现了一种方法来使用按位或者:

var a = 13.6 | 0; //a == 13

我们在谈论它并想知道一些事情。

  • 它是如何工作的?我们的理论是使用这样的运算符将数字转换为整数,从而删除小数部分
  • 它比Math.floor有什么优势吗?也许它快一点? (双关语不打算)
  • 它有任何缺点吗?也许它在某些情况下不起作用?清晰度是显而易见的,因为我们必须弄清楚,而且,我正在写这个问题。

谢谢。

168
Alex Turpin

它是如何工作的?我们的理论是使用这样的运算符将数字转换为整数,从而删除小数部分

除了无符号右移>>>之外的所有按位运算都适用于带符号的32位整数。因此,使用按位运算会将float转换为整数。

做Math.floor有什么优势吗?也许它快一点? (双关语不打算)

http://jsperf.com/or-vs-floor/2 似乎稍快一点

它有任何缺点吗?也许它在某些情况下不起作用?清晰度是显而易见的,因为我们必须弄清楚,而且,我正在写这个问题。

  • 不会传递jsLint。
  • 仅限32位有符号整数
  • 奇数比较行为:Math.floor(NaN) === NaN,而(NaN | 0) === 0
130
Joe

这是 截断 而不是地板。霍华德的回答是正确的;但我想补充一点,Math.floor与负数完全相同。在数学上,这就是一个楼层。

在上面描述的情况下,程序员对 截断 或完全关闭十进制更感兴趣。虽然,他们使用的语法有点模糊了他们将float转换为int的事实。

28
Chad La Guardia

在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
17
zangw

你的第一点是正确的。该数字被转换为整数,因此删除任何十进制数字。请注意,Math.floor向负无穷大舍入到下一个整数,因此在应用于负数时会给出不同的结果。

10
Howard
  • 规范说它被转换为整数:

    让lnum成为ToInt32(lval)。

  • 性能:这已在 jsperf 之前测试过。

注意:删除规范的死链接

5
pimvdb

Javascript表示Number双精度64位浮点数

Math.floor考虑到了这一点。

按位运算在32bit signed integers中工作。 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

也。按位运算不“落地”。它们 truncate ,与说法相同,它们最接近0。一旦你转到负数,Math.floor回合向下,而按位开始舍入向上

正如我之前所说,Math.floor更安全,因为它以64位浮点数运行。 Bitwise 更快 ,是的,但仅限于32位有符号范围。

总结一下:

  • 如果您使用0 to 2147483647工作,Bitwise的工作方式相同。
  • 如果您使用-2147483647 to 0,则按位数为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);
}
2
ShortFuse