2013-08-06 50 views
7

我需要提取用long值一定位範圍,例如:的Java得到位範圍從長

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) 

我知道這可以用位移位和屏蔽來實現,但我不完全知道如何實現這所以它是動態的,每次,因爲每次我需要這樣做,長會有所不同,特定的位範圍也是如此。

我一直在閱讀關於BitSets和BitArrays,但我不完全確定這些都是正確的工作。

任何有關最佳實施方法的建議將不勝感激。

謝謝!

回答

8

要提取nrBits位偏離offset開始,你可以這樣做:

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 - 1L是有long常數。

另請注意,不存在「邊界檢查」(例如,偏移量或大於63的位數或負數)。

+0

只是門票,感謝FGE! – Tony

+1

'''不會工作得很好,因爲'&'最後會刪除符號擴展'1'嗎? (對你有利的角落案例:你在輸入的最左邊界之外提取位,例如nrBits = 32,offset> 32) – zapl

+0

不,它不會。說(用8位來簡化)你有'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; 
+0

您可以使用'1 << n'來代替'pow(2,n)'。你可能是指'&'而不是'&&'。 – arshajii

+0

對不起,單身&,你是對的 - 修復。移動1 n位置也很好,可能會更快。 – user1111284

+0

感謝user1111284! – Tony