2012-06-30 97 views
2

我想知道以下哪些是獲得第i個整數x的最右邊的位,其中i從0開始更快:獲取第i位 - 是%還是更快?

x & (1 << i) 
x >> i % 2 

也很好奇,爲什麼一個快。

謝謝!

+2

它取決於平臺和編譯器。 –

+0

@OliCharlesworth和優化標誌。 – robert

+0

在一個愚蠢的實現中,第一個可能會更快,因爲'&(可能)比'%'更快,並且輪班左右移動。但在某些處理器上,'&'和'%'同樣快,而且更重要的是,除了最笨的編譯器之外,所有的處理器都會將'%2'轉換爲掩碼操作。 –

回答

8

注意

正如評論,這取決於很多因素。另外,你不應該在意。在任何真實的節目中,我不相信你會關注這樣的低級細節。不成熟的優化是時間的可怕浪費。

另外,除非您的平等概念只是零/非零的概念,否則這些不等於操作。

但它是一個有趣的練習

使用GCC與-O3和拆卸我看到:

x & (1 << i) 

The first version 
Dump of assembler code for function op1: 
    0x0000000000000000 <+0>:  mov %esi,%ecx 
    0x0000000000000002 <+2>:  mov $0x1,%eax 
    0x0000000000000007 <+7>:  shl %cl,%eax 
    0x0000000000000009 <+9>:  and %edi,%eax 
    0x000000000000000b <+11>: retq 
End of assembler dump. 

而且

x >> i % 2 

Dump of assembler code for function op2: 
    0x0000000000000010 <+0>:  mov %esi,%ecx 
    0x0000000000000012 <+2>:  sar %cl,%edi 
    0x0000000000000014 <+4>:  mov %edi,%edx 
    0x0000000000000016 <+6>:  shr $0x1f,%edx 
    0x0000000000000019 <+9>:  lea (%rdi,%rdx,1),%eax 
    0x000000000000001c <+12>: and $0x1,%eax 
    0x000000000000001f <+15>: sub %edx,%eax 
    0x0000000000000021 <+17>: retq 

所以這是一個shift leftand Vs的shift rightload effective addressand操作。在這個硬件上看起來非常明顯,速度會更快,但除非你在微控制器上,否則顯然通常不是那麼清楚。讓我們測試它。

我做了一個類似千萬次調用(內聯)操作的循環,並且肯定會返回操作結果的總和,所以編譯器不會把它全部丟掉。

[[email protected] Test]$ gcc -O3 so.c -o so 
[[email protected] Test]$ time ./so 

real 0m0.388s 
user 0m0.384s 
sys  0m0.003s 
[[email protected] Test]$ time ./so 

real 0m0.384s 
user 0m0.380s 
sys  0m0.003s 
[[email protected] Test]$ vi so.c // I changed the function to the second one 
[[email protected] Test]$ gcc -O3 so.c -o so 
[[email protected] Test]$ time ./so 

real 0m0.380s 
user 0m0.377s 
sys  0m0.002s 
[[email protected] Test]$ time ./so 

real 0m0.380s 
user 0m0.379s 

好的夾頭 - 完全一樣。現代超級縮放處理器中有足夠的硬件來隱藏任何差異。

+0

編譯器會產生不同的輸出,因爲如果'x'被簽名並且爲負,則表達式的行爲會有所不同。 – hirschhornsalz

+0

正如我注意到的,即使對於無符號值,它們的行爲也不同,除非您正在測試'== 0'。 –

5

的慣用方法來提取一點或者是

(x >> i) & 1 

這也將類似的多個位工作,或者

x & (1 << i) 

,如果你只是想測試單個位。

注意,在C x不得爲負(優選聲明無符號),並且如果x比需要指定一個1的int較長也是在第二個那麼久。

使用%會使讀者感到困惑,並且可能會有更差的性能,這取決於編譯器。