在瞭解什麼是位運算
以前,讓咱們先來了解什麼是位
?位
指計算機存儲信息的最小單位,在二進制數系統中,位
是經過0或1來表示。在學習一門編程語言的數據類型時,總會告訴咱們 int
的存儲須要 4個字節
,取值範圍爲-2 147 483 648 ~ 2 147 483 647
。其實取值範圍
就是經過 位
計算出來的,因爲 1 字節 = 8 位
,因此 int
中的 1
用二進制表示爲0000 0000 0000 0000 0000 0000 0000 0001
。因此位運算
就是直接對整數在內存中的二進制位進行操做。編程
爲了方便,下面學習中以 int 的 2個字節 演示編程語言
正整數轉換爲二進制一般使用 除二倒取餘
的方法。下面演示經過此方法求 10 、13 、42 的二進制。 學習
0000 0000 0000 1010
,13 的二進制爲
0000 0000 0000 1101
, 42 的二進制爲
0000 0000 0010 1010
。 除了使用
除二倒取餘
的方法,也能夠把二進制位 對應的 十進制表列出來,在進行進制轉換時,只須要把十進制數拆成 表中對應十進制的和就能夠。如:
1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
32768 | 16384 | 8192 | 4096 | 2048 | 1024 | 512 | 256 | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
如:10的二進制:10 = 8 + 2 爲:1010 42的二進制:42 = 32 + 8 + 2 爲:101010 13 的二進制:13 = 8 + 4 + 1 爲:1101ui
在對負整數求二進制時,須要先將負整數對應的正整數轉換成二進制,接着對二進制取反,而後對結果再加一。如求 -10
的二進制:spa
-10 的二進制
先求 10 的二進制
0000 0000 0000 1010
取反:
1111 1111 1111 0101
加 1:
1111 1111 1111 0110
複製代碼
因此 -10
的二進制爲1111 1111 1111 0110
。 注意: 在二進制中的最高位爲符號位
,0 表示爲正數,1表示爲負數,因此int
的最大整數的二進制爲0111 1111 1111 1111 1111 1111 1111 1111
,取值範圍爲: code
位運算能夠對整型數值的各個位進行操做。位運算符包括下面這幾個:cdn
&
:按位與
運算符當兩個整數值 對應位
上都是 1
時,該位返回 1
,不然返回0
(同 1
爲 1
)。如:blog
10 & 13
10 : 0000 0000 0000 1010
13 : 0000 0000 0000 1101
------------------------------------------
結果:0000 0000 0000 1000
複製代碼
|
:按位或
運算符當兩個整數值 對應位
上都是 0
時,該位返回 0
,不然返回1
(同 0
爲 0
)。如:內存
42 | 13
42 : 0000 0000 0010 1010
13 : 0000 0000 0000 1101
------------------------------------------
結果:0000 0000 0010 1111
複製代碼
^
:按位異或
運算符當兩個整數值 對應位
上的數不相同時,該位返回 1
,不然返回0
(不一樣返回1
)。如:string
42 ^ 13
42 : 0000 0000 0010 1010
13 : 0000 0000 0000 1101
------------------------------------------
結果:0000 0000 0010 0111
複製代碼
~
:按位取反
運算符把整數值 對應位
上的數取反,1 變 0, 0 變 1。
42 : 0000 0000 0010 1010
------------------------------------------
~42: 1111 1111 1101 0101
複製代碼
<<
:左移
運算符X << y
把整數X
的二進制位,向左移動y
位。末尾 補 0
。至關於 X * 。
13 << 2
13 : 0000 0000 0000 1101
----------------------------------------
<<2: 0000 0000 0011 0100
13 << 2 的結果爲:52 -----> 13 * (2^2) = 52
複製代碼
>>
:右移
運算符X >> y
把整數X
的二進制位,向右移動y
位。開始處補符號位。至關於 X / 取整數。
13 >> 2
13 : 0000 0000 0000 1101
----------------------------------------
>>2: 0000 0000 0000 0011
13 >> 2 的結果爲:3 -----> 13 / (2^2) = 3
複製代碼
-10 >> 2
-10 : 1111 1111 1111 0110
----------------------------------------
>>2 : 1111 1111 1111 1101
-10 >> 2 的結果爲:-3 -----> -10 / (2^2) = -3
複製代碼
因爲奇數的二進制末尾始終是1
,所以咱們能夠經過x & 1
判斷末尾是否有 1
來決定是不是奇數。
// 經過: a&1 的方式取二進制的最後一位。
#include<stdio.h>
int main(){
int a = -3;
if(a & 1){
printf("奇數:%d\n",a);
}else{
printf("偶數:%d\n",a);
}
return 0;
}
複製代碼
在交換中,^
運算符的運算結果能夠理解成記錄兩個數的不一樣
。比如,我告訴你在一個箱子裏有兩個不同顏色的球(紅,藍)。當用手在裏面拿出一個藍球時,裏面剩下的球不用看,顏色確定是紅色的。
#include<stdio.h>
int main(){
int a = 3;
int b = 2;
printf("a = %d, b = %d\n",a,b);
a = a^b;//告訴 a 和 b 的不一樣的地方,賦值給 a。
b = a^b;// b 經過不一樣記錄 a,就能夠找到原數a,賦值給 b
a = a^b;// 此時b的值是原數a,a 經過不一樣記錄 a,就能夠找到原數b,賦值給 a
printf("a = %d, b = %d\n",a,b);
return 0;
}
複製代碼
經過(x & y) + ((x ^ y) >> 1)
的方式求兩個數的平均數。個人理解是:先經過(x & y)
取兩個數的公共部分,而後經過( x ^ y)
把剩餘部分相加求和經過>> 1
除以2。以十進制數爲例:(12 + 8) / 2 ;12 = 8 + 4, 8 = 8 + 0;因此公共部分是8,剩餘部分是(4 + 0)/2 = 2 ,平均數爲 8 + 2 = 10;
#include<stdio.h>
int avarge(int x, int y){
return (x & y) + ((x ^ y) >> 1);
}
int main(){
int a = 6;
int b = 2;
printf("a = %d, b = %d,平均數:%d\n",a,b,avarge(a,b));
return 0;
}
複製代碼
在二進制中,2 的冪次
的整數是隻含有一個1
,如:
0100
,:
1000
。因此,當咱們去掉最後一位的1
時,結果就變成 0
了。經過x & (x - 1)
來去除最後一位的1
。
#include<stdio.h>
int main(){
int a = 7;
if (a & (a-1)){
printf("a = %d 不是 2 的冪次\n",a);
} else{
printf("a = %d 是 2 的冪次\n",a);
}
return 0;
}
複製代碼
本章學習了 十進制如何轉換爲二進制,位運算的操做符,位運算的簡單應用。