2012-10-29 57 views
1

我想知道我的整數字節的大小。例如:我的int字節數

public static void main(String[] args) throws IOException { 
    int a = 256; 
    System.out.println(nbBytes(a)); 
} 

static byte nbBytes(int value) { 
    byte l = 0; 
    while (value != 0) { 
     value >>>= 8; 
     ++l; 
    } 
    return l; 
} 

它完美的工作,但我想優化這個計算。 你有提議嗎? :D

+0

那麼,你可以使用一個簡單的「如果梯子」。 (但是請注意,你目前的方案會因負數而失敗。) –

+0

就像@HotLicks所說的那樣,每個負數都會返回4。那是你想要的嗎? – Brian

回答

2

如果您指的是運行時性能,以下算法(最初找到最高設置位)可能是最快的。我已經修改了它返回到編碼整數參數所需的字節數:

private static final int[] DE_BRUIJN_BIT_POSITION_LUT = { 
     0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 
     8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 
    }; 

public static int nbBytes2(int n) { 
    n |= n >> 1; 
    n |= n >> 2; 
    n |= n >> 4; 
    n |= n >> 8; 
    n |= n >> 16; 
    return DE_BRUIJN_BIT_POSITION_LUT[((n * 0x07C4ACDD) >> 27) & 0x1f]/8 + 1; 
} 

即使它看起來比較複雜,它不具有任何循環或條件處理,這使得現代CPU的優化使用管道。

將De Bruijn算法與您的方法進行比較,您的方法對於0x0-0xff範圍內的輸入要快4倍(您的方法也不會分支)。對於範圍爲0x100-0xfff的輸入,我的方法速度提高19倍,輸入0x10000-0xffffff快28倍,輸入> 0x1000000速度提高35倍。所有數字都適用於我的硬件,在其他計算機上它可能會有所不同。

+0

這是美麗的。 [This thread](http://stackoverflow.com/questions/7365562/de-bruijn-like-sequence-for-2n-1-how-is-it-constructed)與那些對如何工作感興趣的人有關。 –

1

在Java中,int始終是一個32位帶符號2的補碼值。例如,參見Section 2.3 of the Java Virtual Machine Specification

如果你想知道的最少比特數存儲特定的值,可以使用Integer.numberOfLeadingZeros來獲取:

int bitsNeeded = 32 - Integer.numberOfLeadingZeros(value); 

然後,您可以圍捕獲取所需的字節數。

如果您運行的是舊版本的Java不包括此功能,下面是它的1.6源:

public static int numberOfLeadingZeros(int i) { 
    if (i == 0) 
     return 32; 
    int n = 1; 
    if (i >>> 16 == 0) { n += 16; i <<= 16; } 
    if (i >>> 24 == 0) { n += 8; i <<= 8; } 
    if (i >>> 28 == 0) { n += 4; i <<= 4; } 
    if (i >>> 30 == 0) { n += 2; i <<= 2; } 
    n -= i >>> 31; 
    return n; 
} 

不管這是不是你已經在做只能是更加有效我認爲,通過分析確定。它也將取決於你期望遇到的價值分佈。

如果你只希望處理非負值,我這樣做:

static byte nBytes(int value) { 
    if (value < (1 << 8)) return 1; 
    if (value < (1 << 16)) return 2; 
    if (value < (1 << 24)) return 3; 
    return 4; 
} 

這是假設你需要1個字節來表示爲零。爲了處理負數,有兩個邏輯選擇:

  1. 總是返回4
  2. 返回要代表2的補值字節的最小數量。

對於第二種情況,我會做到以下幾點:

static byte nBytes(int value) { 
    if (value < 0) { 
     if (value > Integer.MIN_VALUE) { 
      value = -value; 
      if (value < (1 << 7)) return 1; 
      if (value < (1 << 15)) return 2; 
      if (value < (1 << 23)) return 3; 
     } 
    } else { 
     if (value < (1 << 8)) return 1; 
     if (value < (1 << 16)) return 2; 
     if (value < (1 << 24)) return 3; 
    } 
    return 4; 
} 
+0

我想他想看看特定值佔用了多少字節。 –

+2

基本上他想知道他需要表示值的最小字節數。例如,30只需要1個字節,而350個需要2個字節。所有負數都需要全部4個字節,因爲您始終需要MSB。 – Brian

+0

@HotLicks - 明白了;更新了答案。 –

0

我不知道這是更優的,但另一種解決方案是一樣的東西(未測試):

return (byte)Math.ceil(Integer.toBinaryString(value).length()/8.0); 
+0

我會給你+1創造性的解決方案。 –