【詳解】位運算符--正數及負數的位運算

位運算符的正負數計算,按位與&,按位或|,按位異或^,按位非~,左移<<,右移>>,以及涉及的碼制相關知識。

一、碼制

二進制數正負數三種表示法——原碼;反碼;補碼。
二進制數的第一位是符號位,0正1負;後面是數值位,

正數的原碼 = 反碼 = 補碼,即符號位爲0,位於首位,隨後是二進制數的絕對值。
示例:5的原碼=0 0000101; 反碼= 0 0000101; 補碼=0 0000101

負數而言,三種表示法是不一樣的。
①原碼:符號位“1”+二進制數絕對值數值
②反碼:符號位“1”+數值位按位取反
③補碼:反碼+“1”(末位)
示例:-5原碼=1 0000101; 反碼=1 1111010; 補碼=1 1111011

二進制反碼和補碼運算性質:
[[X]反]反=[X]原
[[X]補]補=[X]原
[X]反+[Y]反=[X+Y]反(循環進位)
[X]補+[Y]補=[X+Y]補(捨棄進位)

二、位運算符

位運算符對二進制數進行操作,以二進制運算,文章中只使用8位二進制數進行表示,不過在計算機真實使用多少位存儲,讀者可以自己用左右移位運算符試試。 C/C++,JAVA,都是六種位運算符,運算的內在方式一樣。
位運算符 執行原理
按位與 & 兩個操作數同時爲1,結果爲1
按位或 l 兩個操作數只要有一個爲1,結果就爲1
按位異或 ^ 兩個操作數相同,結果爲0,不相同,結果爲1
按位非 ~ 操作數爲1,結果爲0;操作數爲0,結果爲1
左移 << 二進制數整體左移,右側空位補0
右移 >> 二進制數整體右移,左側空位補0

1、二元位運算符的運算

二元位運算符:& ; | ;^ ;<< ;>>
正數之間:位運算是使用他們的原碼進行;
只要有負數:使用補碼進行運算,如果運算結果符號位爲1,那麼需要求運算結果的補碼纔是答案,如果運算結果符號位爲0,那麼答案就是運算結果。

二元位運算符:<< ;>>
正數:左右移運算最終都爲0
負數:左移最終的數值爲0;右移爲保證數值爲負,末尾“+1”

按位與 &

兩個操作數同時爲1,結果爲1

正數
0 0 0 0 0 1 0 0 = 4
0 0 0 0 0 1 0 1 = 5
————————
0 0 0 0 0 1 0 0 = 4 & 5 = 4

正數負數
1 1 1 1 1 1 0 0 = -4補
0 0 0 0 0 1 0 1 = 5
————————
0 0 0 0 0 1 0 0 = -4 & 5 = 4

負數
1 1 1 1 1 1 0 0 = -4補
1 1 1 1 1 0 1 1 = -5補
————————
1 1 1 1 1 0 0 0 = [-4 & -5]補; -4 & -5=[[-4 & -5]補]補 =1 0001000 = -8

按位或 |

兩個操作數只要有一個爲1,結果就爲1

正數
0 0 0 0 0 1 0 0 = 4
0 0 0 0 0 1 0 1 = 5
————————
0 0 0 0 0 1 0 1 = 4 | 5 = 5

正數負數
1 1 1 1 1 1 0 0 = -4補
0 0 0 0 0 1 0 1 = 5補
————————
1 1 1 1 1 1 0 1 = [-4 | -5]補; -4 | -5=[[-4 | -5]補]補 =1 0000011 = -3

負數
1 1 1 1 1 1 0 0 = -4補
1 1 1 1 1 0 1 1 = -5補
————————
1 1 1 1 1 1 1 1 = [-4 | -5]補; -4 | -5=[[-4 | -5]補]補 =1 0000001 = -1

按位異或 ^

兩個操作數相同,結果爲0,不相同,結果爲1

正數
0 0 0 0 0 1 0 0 = 4
0 0 0 0 0 1 0 1 = 5
————————
0 0 0 0 0 0 0 1 = 4 ^ 5 = 1

正數負數
1 1 1 1 1 1 0 0 = -4補
0 0 0 0 0 1 0 1 = 5補
————————
1 1 1 1 1 0 0 1 = [-4 ^ -5]補; -4 ^ -5=[[-4 ^ -5]補]補 =1 0000111 = -7

負數
1 1 1 1 1 1 0 0 = -4補
1 1 1 1 1 0 1 1 = -5補
————————
0 0 0 0 0 1 1 1 = -4 ^ -5 = 7

左移 <<

二進制數整體左移,右側空位補0

正數
0 0 0 0 0 0 0 0 0 1 0 1 = 5
0 0 0 0 0 0 0 1 0 1 0 0 = 5<<2 = 40

負數
0 0 0 0 1 0 0 0 0 1 0 1 = -5
0 0 1 0 0 0 0 1 0 1 0 0 = -5<<2 = -40

右移 >>

二進制數整體右移,左側空位補0

正數
0 0 0 0 0 0 0 0 0 1 0 1 = 5
0 0 0 0 0 0 0 0 0 0 0 1 = 5>>2 = 1

負數
0 0 0 0 1 0 0 0 0 1 0 1 = -5
-5>>2
0 0 0 0 0 0 1 0 0 0 0 1
0 0 0 0 0 0 1 0 0 0 1 0 末尾“+1”
1 0010010 = -5>>2 = -2

2、一元位運算符的運算

一元位運算符:~

按位非 ~

按位非 ~
正數:求取非後的二進制碼的補碼,就是答案
負數:對取非後的二進制碼的求其補碼的兩個步驟顛倒求出來的,就是答案

操作數爲1,結果爲0;操作數爲0,結果爲1

正數
0 0 0 0 0 1 0 1 = 5
~5
1 1 1 1 1 0 1 0
1 0 0 0 0 1 0 1 符號位不變,取反
1 0 0 0 0 1 1 0 符號位不變,末尾加一
~5 = 1 0000110 = -6

負數
1 0 0 0 0 1 0 1 = -5
~(-5)
0 1 1 1 1 0 1 0
0 1 1 1 1 0 1 1 符號位不變,末尾加一
0 0 0 0 0 1 0 0 符號位不變,取反
~(-5) = 0 0000100 = 4

三、測試代碼

大家可以複製來驗證一下上文說的對不對哈哈

void test()
{
	cout << "4 & 5 = " << (4 & 5) << endl;
	cout << "-4 & 5 = " << (-4 & 5) << endl;
	cout << "-4 & -5 = " << (-4 & -5) << endl<<endl;
	cout << "4 | 5 = " << (4 | 5) << endl;
	cout << "-4 | 5 = " << (-4 | 5) << endl;
	cout << "-4 | -5 = " << (-4 | -5) << endl<<endl;
	cout << "4 ^ 5 = " << (4 ^ 5) << endl;
	cout << "-4 ^ 5 = " << (-4 ^ 5) << endl;
	cout << "-4 ^ -5 = " << (-4 ^ -5) << endl<<endl;

	cout << "~5 = " << ~5 << endl;
	cout << "~(-5) = " << ~(-5) << endl<<endl;

	cout << "5<<2 = " << (5 << 3) << endl;
	cout << "-5<<2 = " << (-5 << 3) << endl<<endl;

	cout << "5>>2 = " << (5 >> 2) << endl;
	cout << "-5>>2 = " << (-5 >> 2) << endl<<endl;

	cout << "5<<65 = " << (5 << 65) << endl;
	cout << "-5<<65 = " << (-5 << 65) << endl<<endl;

	cout << "5>>10 = " << (5 >> 10) << endl;
	cout << "-5>>10 = " << (-5 >> 10) << endl<<endl;
}

如有不足之處,還望指正 1


  1. 如果對您有幫助可以點贊、收藏、關注,將會是我最大的動力 ↩︎

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章