Java中Long为何被当作32位处理?
问题分析与解决:Java位移操作的意外结果
我运行了这段Java代码:
public class MyClass { public static void main(String args[]) { long x = 1 << 39; long l = 537150415L; l = l | x; System.out.println(x); System.out.println(l); } }
得到的输出是:
128 537150415
我原本预期x是一个很大的数值,可结果128是2^7,也就是2^(39-32),但long明明是64位的啊?我本来想实现一个能存储1-60范围内数字的位集。
问题根源:整数字面量的默认类型
你遇到的问题核心在于**1是int类型的字面量**,Java里int是32位的有符号整数。当你执行1 << 39时,这个位移操作是在int类型上进行的,而39已经超过了int的32位范围,所以会发生整数溢出,实际等价于1 << (39 % 32),也就是1 << 7,结果自然是128。
哪怕你把结果赋值给long类型变量x,位移操作本身已经在int上完成了,溢出后的结果再被转成long,所以才会得到错误的小数值。
解决方案:使用long类型的字面量进行位移
只需要把1改成1L(long类型的字面量),这样位移操作就会在64位的long上执行,不会出现溢出问题:
public class MyClass { public static void main(String args[]) { long x = 1L << 39; long l = 537150415L; l = l | x; System.out.println(x); System.out.println(l); } }
现在x的值会是549755813888(也就是2^39),l也会正确地把第39位(从0开始计数)置为1,输出符合预期。
关于实现1-60范围的位集
如果是要实现存储1-60的位集,你可以继续用long类型(因为long是64位,足够覆盖1-60的位),每次设置位的时候都记得用1L << n(n是你要设置的位,注意如果是数字1对应第0位的话,要调整偏移,比如数字k对应第k-1位)。比如要设置数字10,就用1L << 9,然后和原long值做或操作即可。
内容的提问来源于stack exchange,提问作者Optimus Prime
相关产品推荐
相关产品推荐

