从整数中获取n个最低有效位

12

这似乎很简单,但我找不到答案。如果我有一个整数 X,在Java中从该整数获取N个最低有效位的最佳方法是什么?


http://docs.oracle.com/javase/tutorial/java/nutsandbolts/opsummary.html - Jayy
3
@KaipaMSarma - 这并没有真正回答他的问题。 - Stephen C
3个回答

14

这个应该适用于所有非负的 N,其中 N < 32:

x & ((1 << N) - 1)

值得详细阐述一下当 N == 31 时,以及 N == 32 这个方法是如何运作的。对于 N == 31,我们得到的值是 1 << N == Integer.MIN_VALUE。从该值中减去 1 后,Java 会自动将其转换为 Integer.MAX_VALUE,这正是你所需要的。对于 N == 32,由于(感谢 @zstring!)<< 操作符只会按照右侧模32位进行位移,因此这种方法不起作用。相反,如果你想避免单独测试这种情况,可以使用以下代码:
```(1L << N) - 1L```
x & ((int)(1L << N) - 1)

通过将long移位,您可以获得完整的32位移位,然后将其强制转换回int,得到0。减去1会得到-1,对于任何intxx & -1都只是x(而xx的低32位的值)。


1 << 32 等于整数值 1,因此对于 N == 32 不起作用。 - zstring
1
@zstring -- 哦,好发现!对于 int 左侧,<< 只使用右参数的低五位,因此它不是通过 32 位移,而是通过 0 位移。我需要修正我的答案。 - Ted Hopp

4
泰德的方法可能会更快,但这里有另一种方法。
x << -N >>> -N

这将所有位向上移动,然后向下移动以截断顶部位。

int i = -1;
System.out.println(Integer.toBinaryString(i));
i = i << -5 >>> -5;
System.out.println(Integer.toBinaryString(i));

打印

11111111111111111111111111111111
11111

1
不错。Java会自动计算移位数量模32,因此这与x << (32 - N) >>> (32 - N)完全相同(除了避免了两个减法)。我不知道哪个更快。我的解决方案使用了一个移位、一个减法和一个按位与运算。你的解决方案使用了两个移位和两个否定运算(如果编译器聪明或程序员提供一些帮助,则只使用一个否定运算)。对于N > 32,我的解决方案的行为就像N == 32一样。你的解决方案总是通过(-N) % 32进行移位,因此对于超出范围的N值,两者并不相等。 - Ted Hopp
是的,但要修改移位数量为模64计算。 - Ted Hopp
很好的一点是,我不需要对我的数据类型的位数大小做出假设,也就是说,即使稍后更改也不会出现一些微妙的错误。 - Peter Lawrey
是的。比起明确地从32(或64)中减去要好得多。我认为我的解决方案也不需要任何假设。 - Ted Hopp

3
您还可以使用掩码。如果您使用位运算符&,则可以删除您想要删除的任何位(例如最高x位)。
int mask = 0x7FFFFFFF                 //Example mask where you will remove the 
                                      // most significant bit 
                                      // (0x7 = 0111b and 0xF = 1111b).
int result = numberToProcess & mask;  //And apply the mask with the &bitwise op.

这样做的缺点是你需要为每个位制作一个掩码,因此也许更好地将其视为一般方法的另一种方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接