2014-01-10 43 views
2

我在識別何時使用XOR運算符進行按位操作時遇到了一些麻煩。按位和和或者非常簡單。如果要屏蔽位,請使用按位AND(常見用例是IP Addressing和子網掩碼)。當你想打開使用包容性或。然而,異或總是讓我感覺好像在面試中被問到一個需要使用XOR的問題時,我永遠不會得到它。有人可以說明何時使用它以及一些常見用例。XOR運算符C

回答

5

您可以使用專用或翻轉位 - ON的位被關閉,反之亦然。例如,這可以方便地交換兩個數字,而不用第三個數字的空間。

0x0A^0xFF = 0x03 (00001010^11111111 = 11110101) 

交換數字:

operation example 
      A  B 
initial: 0011 1010 
a = a^b; 1001 1010 
b = a^b; 1001 0011 
a = a^b; 1010 0011 

正如你可以看到,數字A(在此情況下的半字節)和B被交換,而無需使用額外的空間。這適用於任何兩個相同類型的數字(儘管在C中,按位運算符要求無符號整數)

XOR操作也用於「弱加密」。你可以用一個(重複的)「代碼字」取一個字符串的異或,結果將是一串沒有意義的字節。再次應用相同的操作,然後出現原稿。這是一個相當薄弱的算法,不應該在現實生活中使用。

關於切換位 - 在「過去的日子」裏,如果你想反轉一個圖像,你會爲每個像素做pix = pix & 1 - 或者如果你一次可以做一個字節byte = byte & 0xFF。這會將白色背景上的黑色文字變成黑色背景上的白色文字。我認爲ATARI擁有一項專利,通過與位圖進行異或來在屏幕上的任何位置創建一個閃爍的光標。

類似地,如果您有一個想要創建閃爍燈光的微控制器,重複執行state = state XOR 1將導致狀態切換。

最後,有很多依賴XOR操作的「搗蛋黑客」。例如,計算一個字的奇偶性(即組的位的數目是奇數還是偶數)可以用下面的(來源:http://graphics.stanford.edu/~seander/bithacks.html)完成

unsigned int v; // word value to compute the parity of 
v ^= v >> 16; 
v ^= v >> 8; 
v ^= v >> 4; 
v &= 0xf; 
return (0x6996 >> v) & 1; 

還有許多其他的「聰明的技巧」 - 它們通常會在您嘗試找到執行涉及位操作的最快方法時顯示出來。大多數人可以完美無缺地完成生活,而不需要真正「獲得」它,這沒關係。我,我喜歡擺弄。

+1

是的,異或與零無關,結果位不變。與1異或會總是切換該位。 – Graeme

+0

是啊我想,我覺得我永遠不會意識到何時使用它。 – AyBayBay

+1

@AyBayBay如果您獲得更多的經驗並從事更廣泛的問題,您會有所收穫。這是一個相當罕見的操作,所以不要擔心,如果你沒有遇到它的需要。 –

2

我最喜歡的例子之一是就地交換。 (注:這是C++代碼,而不是C代碼,但你的想法

void swap(int &x, int &y) 
{ 
    x ^= y; 
    y ^= x; 
    x ^= y; 
} 

您還可以切換單位:(n是第N位,其獲取b切換)

a = b^(1 << n) 

另一種不太常見的用途:XOR Linked Lists

  • 您可以保持到下一個和以前的項目,而不是XOR的holdi每個指針指向一個指針。這些日子裏,我們有太多的記憶,可能無所謂,但嘿,它仍然很酷。除了兩個數字,位撥動交換的(除非你是在嵌入式系統上,你需要某種原因雙向鏈表。然後你會很高興你讀這一點。)
+0

使用按位異或交換兩個數字是聰明的 - 在這種情況下,這是一件壞事。首先,如果'x'和'y'指向同一個對象,它就會失敗。只需使用一個臨時的。如果被交換的對象非常大,並且您不能分配臨時對象,則一次使用循環交換一個字節或單詞。 –

+0

至於xor鏈接列表技巧,這同樣*聰明*。當你遍歷它時,它會使列表處於不一致的狀態,對指針的這種位操作嚴格地說是未定義的行爲(儘管你可能會在* most *系統上避開它)。 –

+1

'x'和'y'不能指向同一個對象,它們都是整數。除非你把它叫做swap(x,x)',它什麼也不做。 :) – Keeler

2

其他答案解釋逐位XOR也用於發現的最大的兩個數字,而無需使用if聲明

int max(int x, int y) 
{ 
     return x^((x^y) & -(x < y)); 
} 
+1

從來沒有見過那個,那很性感! – Keeler

+0

不會使用條件分支編譯(x

+0

@Floris;我的意思是說不用'if'。現在更正。 – haccks

2

在創意方面,XOR操作通常用來呈現基於當前的X簡單的方形圖形和給定點的Y座標。例如,一個棋盤看起來很像模式可變單元尺寸:

#include <stdio.h> 

#define CELLSIZE 2 /* cell size is actually 2 power CELLSIZE */ 
#define MASK (1<<CELLSIZE) 

int main() 
{ 
    int i,j; 

    for (i=0;i<32;i++) 
    { 
     for (j=0;j<32;j++) 
      putchar (' '+('*'-' ')*(((i&MASK)^(j&MASK))!=0)); 
     putchar ('\n'); 
    } 
    return 0; 
} 

    **** **** **** **** 
    **** **** **** **** 
    **** **** **** **** 
    **** **** **** **** 
**** **** **** **** 
**** **** **** **** 
**** **** **** **** 
**** **** **** **** 
    **** **** **** **** 
    **** **** **** **** 
    **** **** **** **** 
    **** **** **** **** 
**** **** **** **** 
**** **** **** **** 
**** **** **** **** 
**** **** **** **** 
    **** **** **** **** 
    **** **** **** **** 
    **** **** **** **** 
    **** **** **** **** 
**** **** **** **** 
**** **** **** **** 
**** **** **** **** 
**** **** **** **** 
    **** **** **** **** 
    **** **** **** **** 
    **** **** **** **** 
    **** **** **** **** 
**** **** **** **** 
**** **** **** **** 
**** **** **** **** 
**** **** **** **** 

在視頻遊戲編碼,當你沒有硬件精靈和/或多個playfields,最簡單的方法來繪製一個精靈在頂部一個位圖背景,所以你可以在你方便的時候擦除它,而不必存儲精靈脩改的屏幕部分,就是用背景像素對精靈像素進行異或(一個像素由一位編碼)。要刪除精靈,只需在同一座標處再次繪製即可。也可以看到這種方法在一些非加速顯示硬件上渲染鼠標指針。

0

XOR的應用可以看出,特別是當一個數組被重複,除了一個被重複,並且不重複的單個數字被找到。將所有數字異或將導致僅出現一次的數字。

int arr[]={1, 1, 2, 2, 3, 3, 4}; 
// frequency of every number in the array is 2 except one number. 
int sz=7; //size of array 
int x=0; 
for(int i=0;i<sz;i++) 
    x^=arr[i]; 
// x would give the number 4 here