位運算(參考百科)

程序中的全部數在計算機內存中都是以二進制的形式儲存的。位運算說穿了,就是直接對整數在內存中的二進制位進行操做。html

0表示False,1表示True,空位都當0處理算法

含義 Pascal語言 C語言 Java
按位與 a and b a & b a & b
按位或 a or b a | b a | b
按位異或 a xor b a ^ b a ^ b
按位取反 not a ~a ~a
按位左移 a shl b a << b a << b
無符號右移 a shr b a >> b a >> b
帶符號右移     a>>> b

注意C中的邏輯運算和位運算符號是不一樣的。520|1314=1834,但520||1314=1,由於邏輯運算時520和1314都至關於True。一樣的,!a和~a也是有區別的。數據結構

運算說明

=== 1. and運算 ===加密

and運算一般用於二進制取位操做,例如一個數 and 1的結果就是取二進制的最末位。這能夠用來判斷一個整數的奇偶,二進制的最末位爲0表示該數爲偶數,最末位爲1表示該數爲奇數。spa

相同位的兩個數字都爲1,則爲1;如有一個不爲1,則爲0。htm

00101對象

11100排序

(&;或者and)內存

----------------get

00100

=== 2. or運算 ===

or運算一般用於二進制特定位上的無條件賦值,例如一個數or 1的結果就是把二進制最末位強行變成1。若是須要把二進制最末位變成0,對這個數or 1以後再減一就能夠了,其實際意義就是把這個數強行變成最接近的偶數。

相同位只要一個爲1即爲1。

00101

11100

(|或者or)

----------------

11101

=== 3. xor運算 ===

異或的符號是⊕。按位異或運算, 對等長二進制模式按位或二進制數的每一位執行邏輯按位異或操做. 操做的結果是若是某位不一樣則該位爲1, 不然該位爲0.

xor運算的逆運算是它自己,也就是說兩次異或同一個數最後結果不變,即(a xor b) xor b = a。xor運算能夠用於簡單的加密,好比我想對我MM說1314520,但怕別人知道,因而雙方約定拿個人生日19880516做爲密鑰。1314520 xor 19880516 = 20665500,我就把20665500告訴MM。MM再次計算20665500 xor 19880516的值,獲得1314520,因而她就明白了個人企圖。

相同位不一樣則爲1,相同則爲0。

00101

11100

(^或者xor)

----------------

11001

運算結果

x <- x # y

y <- x @ y

x <- x @ y

執行了第一句後x變成了x # y。那麼第二句實質就是y <- x # y @ y,因爲#和@互爲逆運算,那麼此時的y變成了原來的x。第三句中x實際上被賦值爲(x # y) @ x,若是#運算具備交換律,那麼賦值後x就變成最初的y了。這三句話的結果是,x和y的位置互換了。

加法和減法互爲逆運算,而且加法知足交換律。把#換成+,把@換成-,咱們能夠寫出一個不須要臨時變量的swap過程(Pascal)。

procedure swap(var a,b:longint);

begin

a:=a + b;

b:=a - b;

a:=a - b;

end;

好了,剛纔不是說xor的逆運算是它自己嗎?因而咱們就有了一個看起來很是詭異的swap過程:

procedure swap(var a,b:longint);

begin

a:=a xor b;

b:=a xor b;

a:=a xor b;

end;

注意:位運算版本的交換兩數不適用於一個數的自我交換。也就是說,若是上述程序的"b"改爲"a"的話,其結果是變量a變成零。所以,在使用快速排序時,因爲涉及到一個數的自我交換,所以若是要在其中使用位運算版的交換兩數的話,應該先判斷。具體的時間損耗在此略過。

=== 4. not運算 ===

not運算的定義是把內存中的0和1所有取反。使用not運算時要格外當心,你須要注意整數類型有沒有符號。若是not的對象是無符號整數(不能表示負數),那麼獲得的值就是它與該類型上界的差,由於無符號類型的數是用00到$FFFF依次表示的。下面的兩個程序(僅語言不一樣)均返回65435。

var

a:word;

begin

a:=100;

a:=not a;

writeln(a);

end.

若是not的對象是有符號的整數,狀況就不同了,稍後咱們會在"整數類型的儲存"小節中提到。

=== 5. shl運算 ===

a shl b就表示把a轉爲二進制後左移b位(在後面添b個0)。例如100的二進制爲1100100,而110010000轉成十進制是400,那麼100 shl 2 = 400。能夠看出,a shl b的值實際上就是a乘以2的b次方,由於在二進制數後添一個0就至關於該數乘以2。

一般認爲a shl 1比a * 2更快,由於前者是更底層一些的操做。所以程序中乘以2的操做請儘可能用左移一位來代替。

定義一些常量可能會用到shl運算。你能夠方便地用1 shl 16 - 1來表示65535。不少算法和數據結構要求數據規模必須是2的冪,此時能夠用shl來定義Max_N等常量。

=== 6. shr運算 ===

和shl類似,a shr b表示二進制右移b位(去掉末b位),至關於a除以2的b次方(取整)。咱們也常常用shr 1來代替div 2,好比二分查找、堆的插入操做等等。想辦法用shr代替除法運算可使程序效率大大提升。最大公約數的二進制算法用除以2操做來代替慢得出奇的mod運算,效率能夠提升60%。

優先級

C語言中位運算符之間,按優先級順序排列爲

1

~

2

<<、>>

3

&

4

^

5

|

6

&=、^=、|=、<<=、>>=

相關文章
相關標籤/搜索