2016-08-18 52 views
1

我想切換n次沒有循環。
像1(位)切換3次後會變爲0等等。 對於切換位1次,我使用位^ = 1。 我實際上在搜索一個位操作公式來做到這一點。如何在C/C++中不使用循環切換n次?

+1

你可以給至少3個實際例子和它們各自的結果;你正在嘗試做什麼? – WhiZTiM

+0

恐怕你的問題還不清楚。你能否嘗試更多地解釋它,理想情況下用一個例子(可以是僞代碼)? – Angew

+1

你需要看到切換位還是隻需要結果?如果你所需要的只是結果,這很容易。要麼切換一次,要麼保持獨立,取決於您想要切換的次數。 – NathanOliver

回答

6

週期性如果我理解正確的話,您至少需要2位,你要切換有點N倍。現在

,切換倉N次等於觸發N%的2倍這樣:

b ^= (N%2); 

模2相同​​所以你也可以這樣寫:

b ^= (N&1); 
+0

儘管@shloim回答了這個問題,但是所有的答案取決於「如果你理解正確」......在回答之前嘗試糾正這樣的問題。 –

0

這是不可能的,如果你只有獨立操縱位。

這是因爲一個特定位不知道它的前兩個狀態。

如果你想有一個週期與4

1

廣義解:

int toggle_bit_in_word(int word, int bit, int ntimes) 
{ 
    auto archetype = ntimes & 1; 
    auto toggler = archetype << bit; 
    return word ^= toggler; 
} 

gcc 5.3產生該代碼:

toggle_bit_in_word(int, int, int): 
     and  edx, 1 
     shlx edx, edx, esi 
     mov  eax, edx 
     xor  eax, edi 
     ret 

爲了好玩,讓我們把它寫在naiive方式,享受歡樂:

int toggle_bit_in_word_naiive(int word, int bit, int ntimes) 
{ 
    auto toggler = 1 << bit; 
    while (ntimes--) 
    word ^= toggler; 

    return word; 
} 

輸出(5.3):

toggle_bit_in_word_naiive(int, int, int): 
     mov  ecx, 1 
     mov  eax, edi 
     shlx esi, ecx, esi 
     lea  edi, [rdx-1] 
     test edx, edx 
     je  .L48 
     lea  ecx, [rdx-8] 
     shr  ecx, 3 
     add  ecx, 1 
     lea  r9d, [0+rcx*8] 
     cmp  edi, 12 
     jbe  .L4 
     vmovd xmm1, esi 
     xor  r8d, r8d 
     vpxor xmm0, xmm0, xmm0 
     vpbroadcastd ymm1, xmm1 
.L5: 
     add  r8d, 1 
     vpxor ymm0, ymm0, ymm1 
     cmp  ecx, r8d 
     ja  .L5 
     vpxor xmm1, xmm1, xmm1 
     vperm2i128  ymm2, ymm0, ymm1, 33 
     vpxor ymm0, ymm0, ymm2 
     sub  edi, r9d 
     vperm2i128  ymm2, ymm0, ymm1, 33 
     vpalignr  ymm2, ymm2, ymm0, 8 
     vpxor ymm0, ymm0, ymm2 
     vperm2i128  ymm1, ymm0, ymm1, 33 
     vpalignr  ymm1, ymm1, ymm0, 4 
     vpxor ymm0, ymm0, ymm1 
     vmovd ecx, xmm0 
     xor  eax, ecx 
     cmp  edx, r9d 
     je  .L47 
     vzeroupper 
.L4: 
     xor  eax, esi 
     test edi, edi 
     je  .L48 
     xor  eax, esi 
     cmp  edi, 1 
     je  .L48 
     xor  eax, esi 
     cmp  edi, 2 
     je  .L48 
     xor  eax, esi 
     cmp  edi, 3 
     je  .L48 
     xor  eax, esi 
     cmp  edi, 4 
     je  .L48 
     xor  eax, esi 
     cmp  edi, 5 
     je  .L48 
     xor  eax, esi 
     cmp  edi, 6 
     je  .L48 
     xor  eax, esi 
     cmp  edi, 7 
     je  .L48 
     xor  eax, esi 
     cmp  edi, 8 
     je  .L48 
     xor  eax, esi 
     cmp  edi, 9 
     je  .L48 
     xor  eax, esi 
     cmp  edi, 10 
     je  .L48 
     xor  eax, esi 
     xor  esi, eax 
     cmp  edi, 11 
     cmovne eax, esi 
     ret 
.L47: 
     vzeroupper 
.L48: 
     ret 

8/

當然

時,一個優化器擁有它所需要的所有信息,甚至可以使代碼變得高效:

int main(int argc, char**argv) 
{ 
    return toggle_bit_in_word_naiive(argc, 3, 3); 
} 

結果:

main: 
     mov  eax, edi 
     xor  eax, 8 
     ret