Javascript 整数除法,或者 Math.floor(x) 等于 x | 0 表示 x >= 0?

发布于 2025-01-08 02:50:08 字数 918 浏览 0 评论 0原文

看下面的示例,看起来 Math.floor(x) 相当于 x | 0,对于x >= 0。这是真的吗?如果是,为什么? (或者如何计算x | 0?)

x = -2.9; console.log(Math.floor(x) + ", " + (x | 0));   // -3, -2
x = -2.3; console.log(Math.floor(x) + ", " + (x | 0));   // -3, -2
x = -2;   console.log(Math.floor(x) + ", " + (x | 0));   // -2, -2
x = -0.5; console.log(Math.floor(x) + ", " + (x | 0));   // -1, 0
x = 0;    console.log(Math.floor(x) + ", " + (x | 0));   //  0, 0
x = 0.5;  console.log(Math.floor(x) + ", " + (x | 0));   //  0, 0
x = 2;    console.log(Math.floor(x) + ", " + (x | 0));   //  2, 2
x = 2.3;  console.log(Math.floor(x) + ", " + (x | 0));   //  2, 2
x = 2.9;  console.log(Math.floor(x) + ", " + (x | 0));   //  2, 2
x = 3.1;  console.log(Math.floor(x) + ", " + (x | 0));   //  3, 3

这对于在Javascript中执行整数除法很有用:(5 / 3) | 0 而不是 Math.floor(5 / 3)

Looking at the following examples, it looks like Math.floor(x) is equivalent to x | 0, for x >= 0. Is that really true? If yes, why? (or how x | 0 is calculated?)

x = -2.9; console.log(Math.floor(x) + ", " + (x | 0));   // -3, -2
x = -2.3; console.log(Math.floor(x) + ", " + (x | 0));   // -3, -2
x = -2;   console.log(Math.floor(x) + ", " + (x | 0));   // -2, -2
x = -0.5; console.log(Math.floor(x) + ", " + (x | 0));   // -1, 0
x = 0;    console.log(Math.floor(x) + ", " + (x | 0));   //  0, 0
x = 0.5;  console.log(Math.floor(x) + ", " + (x | 0));   //  0, 0
x = 2;    console.log(Math.floor(x) + ", " + (x | 0));   //  2, 2
x = 2.3;  console.log(Math.floor(x) + ", " + (x | 0));   //  2, 2
x = 2.9;  console.log(Math.floor(x) + ", " + (x | 0));   //  2, 2
x = 3.1;  console.log(Math.floor(x) + ", " + (x | 0));   //  3, 3

This can be useful to perform integer division in Javascript: (5 / 3) | 0 rather than Math.floor(5 / 3).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

傾旎 2025-01-15 02:50:08

位运算符将数字转换为 32 位序列。因此,您建议的替代方案仅适用于带正号的 32 位浮点数,即从 0+2,147,483,647 (2^31-1) 的数字代码>)。

Math.floor(2147483646.4); // 2147483647
2147483646.4 | 0; // 2147483647
// but…
Math.floor(2147483648.4); // 2147483648
2147483648.4 | 0; // -2147483648

另一个区别:如果 x 不是数字,则 x | 的结果0 可能与 Math.floor(x) 不同。

Math.floor(NaN); // NaN
NaN | 0; // 0

除此之外,只要使用正数,结果应该与 Math.floor() 类似。

以下是更多示例+性能测试:http://jsperf.com/rounding-numbers-down

Bitwise operators convert numbers to a 32-bit sequence. So the alternatives you’re suggesting will only work with positive signed 32-bit floats, i.e. numbers from 0 to +2,147,483,647 (2^31-1).

Math.floor(2147483646.4); // 2147483647
2147483646.4 | 0; // 2147483647
// but…
Math.floor(2147483648.4); // 2147483648
2147483648.4 | 0; // -2147483648

Another difference: if x is not a number, the result of x | 0 might be different than that of Math.floor(x).

Math.floor(NaN); // NaN
NaN | 0; // 0

Other than that, the result should be similar to that of Math.floor(), as long as a positive number is used.

Here are some more examples + performance tests: http://jsperf.com/rounding-numbers-down

稍尽春風 2025-01-15 02:50:08

根据 ECMAScript 规范,§11.10 二进制按位运算符:

Semantics
The production A : A @ B, where @ is one of the bitwise operators in the productions 
above, is evaluated as follows:
1. Let lref be the result of evaluating A.
2. Let lval be GetValue(lref).
3. Let rref be the result of evaluating B.
4. Let rval be GetValue(rref).
5. Let lnum be ToInt32(lval).
6. Let rnum be ToInt32(rval).
7. Return the result of applying the bitwise operator @ to lnum and rnum. The result 
   is a signed 32 bit integer.

这是如何x | y 的计算方法:
xy 被解析为 Int32,然后对它们应用 | 运算符。

As per ECMAScript spec, §11.10 Binary Bitwise Operators:

Semantics
The production A : A @ B, where @ is one of the bitwise operators in the productions 
above, is evaluated as follows:
1. Let lref be the result of evaluating A.
2. Let lval be GetValue(lref).
3. Let rref be the result of evaluating B.
4. Let rval be GetValue(rref).
5. Let lnum be ToInt32(lval).
6. Let rnum be ToInt32(rval).
7. Return the result of applying the bitwise operator @ to lnum and rnum. The result 
   is a signed 32 bit integer.

This is how x | y is calculated:
x and y are parsed to Int32 and then apply the | operator to them.

迷离° 2025-01-15 02:50:08

JS中的按位运算是32位的,也就是说float首先被“cast”成“int”。

<代码>“2.6”| 0 = 2 表明正在调用 parseInt

Bitwise operations in JS are 32bit, that is the float is first "cast" into an "int".

"2.6" | 0 = 2 suggests that parseInt is being called.

哀由 2025-01-15 02:50:08

竖线是按位或运算符。由于 0 的位全为零,因此 x|0 理论上是空操作。但为了计算它,操作数必须是整数,因此 x 必须首先从浮点转换为整数。转换是通过消除小数部分来完成的,所以是的,对于某些 x >= 0,我们有 x|0 == Math.floor(x)

请注意,结果取决于内部整数类型的大小和符号。例如你得到:

2147483648|0     == -2147483648     // 0x80000000
Math.pow(2,32)|0 == 0               // the lowest 32 bits are all 0

The vertical bar is the bitwise-or operator. Since the bits of 0 are all zero, x|0 is in theory a no-op. But in order to evaluate it the operands must be integers, so x must be converted from floating point into an integer first. The conversion is made by eliminating the fractional part, so yes, for some x >= 0 we have x|0 == Math.floor(x).

Note that the result depends on the size and signness of the internal integer type. For example you get:

2147483648|0     == -2147483648     // 0x80000000
Math.pow(2,32)|0 == 0               // the lowest 32 bits are all 0
故乡的云 2025-01-15 02:50:08

(x | 0) 删除了“.”之后的位,因此我们可以得到下一个真关系:

x | 0 = (x < 0 ? -1 : 1) * Math.floor(Math.abs(x)) ;

x >>> 0 与 x | 具有相同的效果0,所以:

x >> 0 = x | 0 = (x < 0 ? -1 : 1) * Math.floor(Math.abs(x)) ;

(x | 0) removes the bits after the ".", so we can get the next true relation:

x | 0 = (x < 0 ? -1 : 1) * Math.floor(Math.abs(x)) ;

x >> 0 has the same effect as x | 0, so :

x >> 0 = x | 0 = (x < 0 ? -1 : 1) * Math.floor(Math.abs(x)) ;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文