位運(yùn)算 看這篇就夠了

前言
不知道大家是不是像我之前一樣一看到二進(jìn)制丶十六進(jìn)制就頭大,更別說位運(yùn)算了,也不知道位運(yùn)算的作用是啥,索性花了一些時(shí)間整理出這些知識(shí)點(diǎn)。
我們知道程序中的所有數(shù)在計(jì)算機(jī)內(nèi)存中都是以二進(jìn)制的形式儲(chǔ)存的。位運(yùn)算就是直接對(duì)整數(shù)在內(nèi)存中的二進(jìn)制位進(jìn)行操作。
在系統(tǒng)軟件中,常常需要處理二進(jìn)制位的問題。C語言提供了6個(gè)位操作運(yùn)算符。這些運(yùn)算符只能用于整型操作數(shù),即只能用于帶符號(hào)或無符號(hào)的char,short,int與long類型。
而二進(jìn)制有8位(最低)丶 16位 丶32位 丶64位甚至更多,我們要怎樣進(jìn)行 這令人愉悅的折磨呢 位運(yùn)算呢?
X進(jìn)制與二進(jìn)制
既然位運(yùn)算操作的是二進(jìn)制數(shù),就需要先把其他數(shù)轉(zhuǎn)換成二進(jìn)制. 如果你已經(jīng)知道如何進(jìn)制轉(zhuǎn)換可以跳到位運(yùn)算這段。
首先看下十進(jìn)制轉(zhuǎn)二進(jìn)制
125轉(zhuǎn)換成二進(jìn)制是01111101,計(jì)算方法很簡單正十進(jìn)制數(shù)除以二,得到的商再除以二,依次類推直到商為零時(shí)為止,然后在旁邊標(biāo)出各步的余數(shù),最后倒著寫出來,再根據(jù)實(shí)際高位補(bǔ)零,即除二取余,倒序排列,高位補(bǔ)零。
/* 以下是計(jì)算過程 商/2 --------- 余數(shù) */ 125/2 --------- 1 62/2 --------- 0 31/2 --------- 1 15/2 --------- 1 7/2 --------- 1 3/2 --------- 1 1/2 --------- 1 0
將余數(shù)倒置則是1111101,然后我們發(fā)現(xiàn)結(jié)果只有7位數(shù),而二進(jìn)制最低位是8位,所以進(jìn)行高位補(bǔ)零之后得到他的最終結(jié)果01111101
前置知識(shí):被除數(shù)÷除數(shù)=商··· ···余數(shù) 例: 10 ÷ 3 =3... ... 1
二進(jìn)制轉(zhuǎn)X進(jìn)制
知道了十進(jìn)制轉(zhuǎn)二進(jìn)制,那你知道反過來該怎么算嗎?
將二進(jìn)制中的位數(shù)分別與對(duì)應(yīng)的值相乘,然后相加得到的就為十進(jìn)制
我們看到01111101這個(gè)二進(jìn)制,它是一個(gè)八位數(shù),從低位(最右邊)開始計(jì)算,分別乘對(duì)應(yīng)的值,最后相加,那如何區(qū)分一個(gè)二進(jìn)制是正數(shù)還是負(fù)數(shù)呢?當(dāng)然是看首位,首位為1為負(fù)數(shù),首位為0為正數(shù),這里的首位指的是二進(jìn)制的頭一個(gè)數(shù),而不是位數(shù)的最低位(計(jì)算是從低位開始,判斷正負(fù)則看首位)。
二進(jìn)制: 0 1 1 1 1 1 0 1 第幾位: 7 6 5 4 3 2 1 0? ? ? ? =(1*2^0)+(0*2^1)+(1*2^2)+(1*2^3)+(1*2^4)+(1*2^5)+(1*2^6)+(0*2^7) ? ? ? = 1+0+4+8+16+32+64+0 ? ? ? = 125
這樣就得出了結(jié)果125,然后首位為0則是正125。
其他進(jìn)制轉(zhuǎn)二進(jìn)制
8進(jìn)制丶16進(jìn)制 2進(jìn)制等相互轉(zhuǎn)換其實(shí)是很簡單的,因?yàn)槠溆袑?duì)應(yīng)關(guān)系
8 = 2^3 (8→2)取一分三 (2→8)取三合一 16 = 2^4 (16→2)取一分四 (2→16)取四合一 32 = 2^5 (32→2)取一分五 (2→32)取五合一 ... //即二進(jìn)制分組 二進(jìn)制 01111101 分組(取四合一) 0111 1101 計(jì)算對(duì)應(yīng)數(shù) 7 D
負(fù)數(shù)轉(zhuǎn)二進(jìn)制
上面說的是正整數(shù)轉(zhuǎn)二進(jìn)制的方法,那么負(fù)數(shù)呢?
如果你已經(jīng)知道了一個(gè)正十進(jìn)制數(shù)的二進(jìn)制結(jié)果,那么他的負(fù)十進(jìn)制數(shù)的二進(jìn)制結(jié)果則是:
二進(jìn)制取反,然后對(duì)結(jié)果再加一
如何理解呢,我們已經(jīng)算出125的二進(jìn)制(8位情況下)表示是01111101,取反的意思則是0變成1,1變成0,結(jié)果是10000010,然后加一,而二進(jìn)制逢二進(jìn)一,所以得出得結(jié)果為10000011,所以-125的二進(jìn)制在8位的顯示中為10000011。
為什么要說在八位的顯示中?
如果是在16位 32位有何不同?
你可能會(huì)發(fā)現(xiàn)一個(gè)問題,如果用10000011反過來計(jì)算十進(jìn)制的話,會(huì)發(fā)現(xiàn)他是131 而不是-125,為什么會(huì)這樣呢?
那是因?yàn)橛蟹?hào)和無符號(hào)的表示方式不同,在java中byte,short,int,long都是有符號(hào)的,他們也有對(duì)應(yīng)的位數(shù)和范圍(以下^代表冪):
符號(hào) | 占位 | 字節(jié) | 范圍 |
---|---|---|---|
byte | 8 | 1 | -2^7 ~ 2^7-1(-128 ~ 127) |
short | 16 | 2 | -2^15 ~ 2^15-1 |
int | 32 | 4 | -2^31 ~ 2^31-1 |
long | 64 | 8 | -2^63 ~ 2^63-1 |
當(dāng)定義八位(byte)-125時(shí)它代表的八位二進(jìn)制是10000011,當(dāng)你反過來算時(shí)得到的值131>八位(byte)的范圍,所以他并不能用byte表示。
byte a = 131; //錯(cuò)誤 范圍超出
所以當(dāng)10000011用來表示八位二進(jìn)制是-125
正確算法應(yīng)該是把正數(shù)轉(zhuǎn)負(fù)數(shù)的步驟逆向運(yùn)算,正數(shù)轉(zhuǎn)負(fù)數(shù)時(shí)我們是取反再加一,反過來當(dāng)范圍超需要表示為負(fù)數(shù)時(shí)減一取反才得出的結(jié)果才是正確的值,然后再根據(jù)首位為1是負(fù)數(shù)(轉(zhuǎn)換之前的首位),為0是正數(shù)確定符號(hào)。
(byte) 1000 0011 = -125 (short)0000 0000 1000 0011 = 131 (short)1111 1111 1000 0011 = -125
以上就是關(guān)于各進(jìn)制與二進(jìn)制之間的轉(zhuǎn)換了。
位運(yùn)算
接下來我們看一下如何進(jìn)行位運(yùn)算,位運(yùn)算到底有什么用呢?
- 大部分時(shí)候我們不會(huì)用到位運(yùn)算,特別是碼農(nóng)時(shí)代,明了直接才更有用。但是位運(yùn)算就沒有用處了么?不是,位運(yùn)算的作用大多體現(xiàn)在研究類運(yùn)用。位運(yùn)算生澀難懂,不過有個(gè)很明顯的優(yōu)勢(shì)就是特別快。因?yàn)檫@是計(jì)算機(jī)看的語言,也是內(nèi)部運(yùn)算的語言."
- *如果在平時(shí)編程當(dāng)中如果正常的運(yùn)算能更讓人理解的話是沒必要使用位運(yùn)算表示的,強(qiáng)行使用無異于炫技罷了,代碼是讓人看的。
位取反(~)
位取反即之前負(fù)數(shù)轉(zhuǎn)二進(jìn)制所用的方式,即0變1,1變0。
10001100 01110011
位與(&)
位與即如果兩個(gè)位進(jìn)行比較兩位同時(shí)為1,結(jié)果才為1,否則結(jié)果為0。
例如: 125 & 7
125 & 7 二進(jìn)制: 01111101 & 00000111 位與比較: 0 1 1 1 1 1 0 1 --------------- 0 0 0 0 0 1 1 1 | | | | | | | | × × × × × √ × √ | | | | | | | | 0 0 0 0 0 1 0 1 結(jié)果: 125&7 = 0000 0111 = 5
位或(|)
位或即如果兩個(gè)位進(jìn)行比較兩位同時(shí)為0,結(jié)果才為0,否則結(jié)果為1。
例如: 125 | 7
125 | 7 二進(jìn)制: 01111101 | 00000111 位或比較: 0 1 1 1 1 1 0 1 --------------- 0 0 0 0 0 1 1 1 | | | | | | | | √ × × × × × × × | | | | | | | | 0 1 1 1 1 1 1 1 結(jié)果: 125|7 = 0111 1111 = 7
異或(^)
位異或即如果兩個(gè)位進(jìn)行比較相同取0,不同取1。
例如: 125 ^ 7(java中^代表異或)
125 ^ 7 二進(jìn)制: 01111101 ^ 00000111 位異或比較: 0 1 1 1 1 1 0 1 --------------- 0 0 0 0 0 1 1 1 | | | | | | | | √ × × × × √ × √ | | | | | | | | 0 1 1 1 1 0 1 0 結(jié)果: 125^7 = 0111 1010 = 122
異或的幾條性質(zhì):
1、交換律
2、結(jié)合律 (a^b)^c == a^(b^c)
3、對(duì)于任何數(shù)x,都有 x^x=0,x^0=x
4、自反性: a^b^b=a^0=a;
編程算法中的作用:交換兩個(gè)數(shù)(利用性質(zhì))
public void Swap(int &a, int &b){ if (a != b){ a ^= b; //a=a^b b ^= a; //b=b^(a^b) = (b^b)^a = a a ^= b; //a=(a^b)^a = (a^a)^b = b } }
右移(>>)
將一個(gè)數(shù)的各二進(jìn)制位全部右移若干位,正數(shù)左補(bǔ)0,負(fù)數(shù)左補(bǔ)1,右邊丟棄。
125>>3
125 >> 3 右移: 0 1 1 1 1 1 0 1 --------------- 0 0 1 1 1 1 1 0 |1 >> 1 0 0 0 1 1 1 1 1 |0 1 >> 2 0 0 0 0 1 1 1 1 |1 0 1 >> 3 ^ ^ ^ 正數(shù)補(bǔ)0負(fù)數(shù)補(bǔ)1 結(jié)果: 125>>3 = 0000 1111 = 15 等價(jià)與 125/2的3次方的商
左移(<<)
同樣的,左移則是將一個(gè)運(yùn)算對(duì)象的各二進(jìn)制位全部左移若干位(左邊的二進(jìn)制位丟棄,右邊補(bǔ)0)。
125>>3
125 >> 3 右移: 0 1 1 1 1 1 0 1 --------------- 0|1 1 1 1 1 0 1 0 << 1 0 1|1 1 1 1 0 1 0 0 << 2 0 1 1|1 1 1 0 1 0 0 0 << 3 ^ ^ ^ 補(bǔ)0 結(jié)果: 125<<3 = 1110 1000 = -24(八位) 125<<3 = 1110 1000 = 1000(十六位) 相當(dāng):125*2的3次方(若左移時(shí)舍棄的高位不包含1)
無符號(hào)右移(>>>)
無符號(hào)右移則始終補(bǔ)0,不考慮正負(fù)數(shù)。
總結(jié):
符號(hào) | 描述 | 運(yùn)算規(guī)則 |
---|---|---|
~ | 反 | 1變0,0變1 |
& | 與 | 兩個(gè)位都為1時(shí),結(jié)果才為1 |
| | 或 | 兩個(gè)位都為0時(shí),結(jié)果才為0 |
^ | 異或 | 兩個(gè)位相同為0,相異為1 |
>> | 右移 | 各二進(jìn)位全部左移若干位,高位丟棄,低位補(bǔ)0 |
<< | 左移 | 各二進(jìn)位全部右移若干位,對(duì)無符號(hào)數(shù),高位補(bǔ)0,有符號(hào)數(shù),各編譯器處理方法不一樣,有的補(bǔ)符號(hào)位(算術(shù)右移),有的補(bǔ)0(邏輯右移) |
MENMORY TOAST >>>>>>
到此這篇關(guān)于位運(yùn)算 看這篇就夠了的文章就介紹到這了,更多相關(guān)位運(yùn)算內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持腳本之家!
相關(guān)文章
FTTC/FTTH和FTTR有什么區(qū)別? 光纖接入方式詳細(xì)介紹
國內(nèi)主流 ISP 普遍都采用了光纖連接,常見術(shù)語包括 FTTC(光纖到路邊)、FTTB(光纖到樓宇)、FTTH(光纖到戶)和 FTTR(光纖到房間),他們之間有什么區(qū)別?詳細(xì)如下2025-03-05TP-Link PDDNS服將于務(wù)6月30日正式停運(yùn):用戶需轉(zhuǎn)向第三方DDNS服務(wù)
近期,路由器制造巨頭普聯(lián)(TP-Link)在用戶群體中引發(fā)了一系列重要變動(dòng),上個(gè)月,公司發(fā)出了一則通知,明確要求所有用戶必須通過實(shí)名認(rèn)證流程,方能繼續(xù)使用其提供的DDNS服2025-02-15電腦怎么查看隱藏和顯示SSID? 服務(wù)集標(biāo)識(shí)符等你來揭秘
之前我們介紹過ssid的概念,那么自己的設(shè)備怎么顯示ssid和隱藏ssid呢?下面我們就來看看詳細(xì)的教程2025-01-14SSID究竟是什么? WiFi網(wǎng)絡(luò)名稱及工作方式解析
SID可以看作是無線網(wǎng)絡(luò)的名稱,類似于有線網(wǎng)絡(luò)中的網(wǎng)絡(luò)名稱或者路由器的名稱,在無線網(wǎng)絡(luò)中,設(shè)備通過SSID來識(shí)別和連接到特定的無線網(wǎng)絡(luò)2025-01-14向日葵Q2Pro怎么樣? 貝銳向日葵Q2Pro工業(yè)級(jí)遠(yuǎn)控設(shè)備測(cè)評(píng)
今天帶來的這款向日葵 Q2Pro ,就是一款專門用于工業(yè)設(shè)備、醫(yī)療設(shè)備等遠(yuǎn)程控制的硬件產(chǎn)品,憑借其即插即用、斷網(wǎng)可遠(yuǎn)控、無需被控主機(jī)安裝軟件等特性,為設(shè)備維護(hù)帶來了全2024-11-23雙頻BE5100面板AP! TP-LINK TL-7AP5100HI-PoE拆機(jī)測(cè)評(píng)
TP-LINK一款為TL-7AP5100HI-PoE 易展版的 Wi-Fi 7 AP 面板怎么樣?該面板隸屬 BE5100 規(guī)格家族,詳細(xì)請(qǐng)看下文拆機(jī)測(cè)評(píng)2024-06-28AP2.4g和5g的wifi區(qū)別 無線網(wǎng)2.4g和5g有什么區(qū)別
AP2.4g和5g的wifi區(qū)別 無線網(wǎng)2.4g和5g有什么區(qū)別WIFI這一名詞可謂是家喻戶曉,但是你知道2.4g和5g wifi的區(qū)別嗎2024-01-03- 無線路由器根據(jù)不同用戶群體的需求,提供了多種工作模式,只有選對(duì)了模式,才能充分發(fā)揮路由器的作用,路由器常見的三大工作模式為:路由模式、中繼模式和AP模式,不同的模2023-12-26
SSU雙口2.5g軟路由群暉有線電口網(wǎng)卡測(cè)評(píng)
第一次測(cè)評(píng)PCIe 3.0 x1的雙口2.5G網(wǎng)卡,下面我們就來看看SSU雙口2.5G網(wǎng)卡拆機(jī)和測(cè)試雙口有沒有瓶頸2023-12-12一篇文章告訴你公網(wǎng),私網(wǎng),內(nèi)網(wǎng),外網(wǎng)的區(qū)別
最近經(jīng)常有很多小白朋友在后臺(tái)問,公網(wǎng)、私網(wǎng)、內(nèi)網(wǎng)、外網(wǎng),這些的概念是啥樣的,又該怎么去界定2023-09-06