在 Java 中对 long 进行位移

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22330107/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 14:59:05  来源:igfitidea点击:

Bitshifting a long in Java

javabit-shift

提问by Dori

Im sure this is an easy one for whoever sees it first!

我敢肯定,对于第一个看到它的人来说,这很容易!

Why in Java does code like

为什么在 Java 中代码像

   long one = 1 << 0;
   long thirty = 1 << 30;
   long thirtyOne = 1 << 31;
   long thirtyTwo = 1 << 32;

   System.out.println(one+" = "+Long.toBinaryString(1 << 0));
   System.out.println(thirty+" = "+Long.toBinaryString(1 << 30));
   System.out.println(thirtyOne+" = "+Long.toBinaryString(1 << 31));
   System.out.println(thirtyTwo+" = "+Long.toBinaryString(1 << 32));

print

打印

1 = 1
1073741824 = 1000000000000000000000000000000
-2147483648 = 1111111111111111111111111111111110000000000000000000000000000000
1 = 1

This does not make sense to me. longis a 64 bit number - whereas it seems to act like an intin the above. I know bitshifted bytes undergo int promotion but I dont see whats going on in this case.

这对我来说没有意义。long是一个 64 位数字 - 而它的作用似乎类似于int上面的 。我知道 bitshifted bytes 进行 int 升级,但我不知道在这种情况下发生了什么。

Any pointers on whats going on here would be good :)

任何关于这里发生的事情的指示都会很好:)

Thx

谢谢

EDIT: thanks for all the answers - i realised what was going on as soon as I clicked 'submit' but SO went into readonlymode and I couldnt delete! Many thanks!

编辑:感谢所有的答案 - 我一点击“提交”就意识到发生了什么,但进入readonly模式,我无法删除!非常感谢!

采纳答案by Bathsheba

It's because 1 is an intliteral, so <<is applied to an integer. The result is cast to a long, but by then it's too late.

这是因为 1 是一个int文字,所以<<适用于一个整数。结果被转换为 a long,但为时已晚。

If you write 1L << 32, etc., then all will be well. Lis used to denote a longliteral.

如果你写 1L << 32,那么一切都会好起来的。L用于表示long文字。

回答by arshajii

Well you're using int literals, which behave like ints. Use a long literal (i.e. 1L) instead:

好吧,您正在使用 int 文字,其行为类似于 int。改用长文字(即1L):

System.out.println(1 << 31);
System.out.println(1L << 31);  // <--
-2147483648
2147483648

When you have an expression like 1 << 31, it evaluates to a fixed value irrespective of what it's being assigned to, be it intor long.

当你有一个像 的表达式时1 << 31,它的计算结果是一个固定的值,而不管它被分配给什么,是它int还是long

回答by DanielBarbarian

This is because the number 1in the line long thirtyTwo = 1 << 32;is an intby default. You need to explicit mark it as a long before you do the shift operation. What happens now is that you do a shift on an intwhich then after the shift is done is casted from an intto a long.

这是因为该1行中的数字默认long thirtyTwo = 1 << 32;为 an int。您需要在执行移位操作之前将其显式标记为 long。现在发生的事情是,您对 an 进行了转换int,然后在转换完成后将其从 an 转换int为 a long

   long one = 1l << 0;
   long thirty = 1l << 30;
   long thirtyOne = 1l << 31;
   long thirtyTwo = 1l << 32;

回答by Tillerino

The problem is that 1is an integer. It will be converted to a long afterthe shift. Try

问题是这1是一个整数。它将在移位转换为 long 。尝试

   long one = 1l << 0;
   long thirty = 1l << 30;
   long thirtyOne = 1l << 31;
   long thirtyTwo = 1l << 32;

回答by Jesper

First of all:

首先:

Java Language Specification paragraph 15.19

Java 语言规范第 15.19 段

Shift Operators

If the promoted type of the left-hand operand is int, only the five lowest-order bits of the right-hand operand are usedas the shift distance. It is as if the right-hand operand were subjected to a bitwise logical AND operator & (§15.22.1) with the mask value 0x1f (0b11111). The shift distance actually used is therefore always in the range 0 to 31, inclusive.

If the promoted type of the left-hand operand is long, then only the six lowest-order bits of the right-hand operand are usedas the shift distance. It is as if the right-hand operand were subjected to a bitwise logical AND operator & (§15.22.1) with the mask value 0x3f (0b111111). The shift distance actually used is therefore always in the range 0 to 63, inclusive.

移位运算符

如果左侧操作数的提升类型为 int,则仅将右侧操作数的最低 5 位用作移位距离。就好像右手操作数受制于掩码值为 0x1f (0b11111) 的按位逻辑 AND 运算符 &(第 15.22.1 节)。因此实际使用的移动距离总是在 0 到 31 的范围内,包括 0 到 31。

如果左侧操作数的提升类型为 long,则仅将右侧操作数的 6 个最低位用作移位距离。就好像右手操作数受制于掩码值为 0x3f (0b111111) 的按位逻辑 AND 运算符 &(第 15.22.1 节)。因此,实际使用的移位距离始终在 0 到 63 的范围内,包括 0 到 63。

So, why does it work as if you are shifting ints instead of longs? Because you are shifting ints! Try using a longliteral instead:

那么,为什么它会像移动ints 而不是longs 一样工作?因为你在换ints!尝试使用long文字代替:

long thirtyTwo = 1L << 32;

回答by mauretto

literal 1 is an int. Use 1L (L as long) and retry.

文字 1 是一个整数。使用 1L(L 一样长)并重试。

回答by Pierre Rust

It acts like an intbecause you are shifting ints ! To shift a long, you must suffix all your number with l.

它的行为就像是int因为你正在转移整数!要移动 long,您必须在所有号码后加上l.

long one = 1l << 0;
long thirty = 1l << 30;
long thirtyOne = 1l << 31;
long thirtyTwo = 1l << 32;

System.out.println(one+" = "+Long.toBinaryString(1l << 0));
System.out.println(thirty+" = "+Long.toBinaryString(1l << 30));
System.out.println(thirtyOne+" = "+Long.toBinaryString(1l << 31));
System.out.println(thirtyTwo+" = "+Long.toBinaryString(1l << 32));

Which gives the following result :

这给出了以下结果:

1 = 1
1073741824 = 1000000000000000000000000000000
2147483648 = 10000000000000000000000000000000
4294967296 = 100000000000000000000000000000000