鏈接地址:【詳解】位運算符--正數及負數的位運算
位運算符的正負數計算,按位與&,按位或|,按位異或^,按位非~,左移<<,右移>>,以及涉及的碼制相關知識。
一、碼制
二進制數正負數三種表示法——原碼;反碼;補碼。
二進制數的第一位是符號位,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;右移為保證數值為負,末尾“+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>>65 = " << (5 >> 10) << endl;
cout << "-5>>65 = " << (-5 >> 10) << endl<<endl;
}
如有不足之處,還望指正 [1]。
如果對您有幫助可以點個贊或關注,將會是我最大的動力 ↩︎