2012-12-28 83 views
1

我有一個方法,使用下面的方法來提取最顯著,非零在一個整數字節:如何在沒有while循環的情況下獲得32位整數中最重要的非零字節?

private static int getFirstByte(int n) 
{ 
    while (n > 0xFF) 
     n >>= 8; 

    return n; 
} 

有與該方法的邏輯問題。整數參數可能是負數,這意味着它會返回傳入的數字,這是不正確的。

該方法本身也有可能存在問題。它使用了一個while循環。

有沒有一種方法來執行這個邏輯沒有一個while循環,也可能避免不正確地返回負數的結果?

+1

爲什麼是while循環的問題嗎?無論如何,這裏只有四個字節,所以你可以寫下四個明確的步驟。 – Thilo

+0

如果我可以在沒有for循環的情況下執行相同的操作,它將會少於運行時指令。這不是瓶頸,但儘管如此,它仍然很高興知道。 – Brad

+0

您的工具鏈可能會提供直接映射到快速硬件指令的「計數前導零」內在值,例如, __builtin_clz()在gcc中。一旦你有numzeros = clz(n),你可以用(((unsigned int)n)>>((sizeof(int) - (numzeros/8))* 8))&0xff這樣的代碼來提取字節, -zero n。請注意,負數的右移會在C中調用未定義的行爲,因此將轉換爲unsigned int。類似地,等於操作數大小的移位量導致未定義的行爲,這就是n不能爲零的原因。 – njuffa

回答

1

我想通過獲得第一非0 byteint您的意思是int的自然8位中斷,而不是動態的8位中斷。

自然8位符:

00000000|00010110|10110010|11110001 ==>00010110

動態8位突破:

00000000000|10110101|1001011110001 ==>10110101

這將返回上int的自然8位斷裂第一非零byte沒有循環或支化。此代碼可能會或可能不會更有效,然後paulsm4的答案。請務必對代碼進行基準測試和/或分析,以確定哪種方法最適合您。

Java代碼:ideone link

class Main { 
    public static void main(String[] args) { 
     int i,j; 
     for (i=0,j=1; i<32; ++i,j<<=1) { 
      System.out.printf("0x%08x : 0x%02x\n",j,getByte(j)); 
     } 
    } 
    public static byte getByte(int n) { 
     int x = n; 
     x |= (x >>> 1); 
     x |= (x >>> 2); 
     x |= (x >>> 4); 
     x |= (x >>> 8); 
     x |= (x >>> 16); 
     x -= ((x >>> 1) & 0x55555555); 
     x = (((x >>> 2) & 0x33333333) + (x & 0x33333333)); 
     x = (((x >>> 4) + x) & 0x0f0f0f0f); 
     x += (x >>> 8); 
     x += (x >>> 16); 
     x &= 0x0000003f; 
     x = 32 - x;  // x now equals the number of leading zeros 
     x &= 0x00000038; // mask out last 3 bits (cause natural byte break) 
     return (byte)((n&(0xFF000000>>>x))>>>(24-x)); 
    } 
} 
+0

我印象深刻!位算術被帶到下一級。 :) – Brad

+1

@Brad上面的代碼*可能會被減少到更少的操作,但我不想探索這種可能性。 –

2

您可以使用log n/log 256 ...但是,那麼你會遇到更大的問題。

3

不聰明,不優雅 - 但我相信它確實「提取最顯著,非零整數字節...不使用循環」:

private static int getFirstByte(int n) { 
    int i; 
    if ((i = n & 0xff000000) != 0) 
    return (i >> 24) & 0xff; 
    if ((i = n & 0xff0000) != 0) 
    return (i >> 16) & 0xff; 
    if ((i = n & 0xff00) != 0) 
    return (i >> 8) & 0xff; 
    // all of the higher bytes are zeroes 
    return n; 
} 
相關問題