从一个长整型数中获取位范围的Java代码

11

我需要从一个长整型值中提取特定的位范围,例如:

long input = 15367 (11110000000111)

我需要做的是从原始长整型值中提取两个长整型数值。

First long is 5 bits starting from bit 0, so bits 0:4 = 7 (0111)
Second long is 56 bits starting from bit 8, so bits 7:55 = 60 (1111000)

我知道这可以通过位移和掩码来完成,但是我不太确定如何实现动态性,因为每次需要执行此操作时,长整型将会不同,特定的位范围也会不同。

我一直在阅读关于BitSet和BitArray的文章,但我并不确定它们是否适合此工作。

如何最好地实现这一点的任何建议都将不胜感激。

谢谢!

2个回答

13

要从偏移量offset开始提取nrBits位,您可以执行以下操作:

public static long extractSub(final long l, final int nrBits, final int offset)
{
    final long rightShifted = l >>> offset;
    final long mask = (1L << nrBits) - 1L;
    return rightShifted & mask;
}

请注意使用 >>> 右移运算符的用户;这样您就不必携带符号位。

至于 (1L << nrBits) - 1L,即为 2^nrBits - 1。其中的 L 是为了表示常量的类型为 long

还要注意,没有进行“边界检查”(例如,偏移量或位数大于 63 或为负数)。


1
“>>” 也能用,因为末尾的“&”会移除符号扩展的“1”吗?(这是一个有利于你的边角情况:你提取了输入左侧范围之外的位,例如nrBits=32,offset>32) - zapl
不会。假设您有10001111并希望从偏移量3开始提取三个位:如果使用>>>,则右移将给出00010001,但是使用>>将给出11110001(符号位被传递)。 - fge

2
为了从位x和位y之间提取比特,其中x是这两个数字中较大的一个,您可以使用以下语句:
long mask = (Math.pow(2,x+1)-1)- (Math.pow(2,y+1)-1);
long extract = input & mask;

你可以使用 1 << n 代替 pow(2,n)。而且你可能是想用 & 而不是 && - arshajii
抱歉,单个&是正确的 - 已修复。将1向左移n位也不错,可能更快。 - user1111284

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