亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.430618.com 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

基本概念

1、當(dāng)前常見的CPU位數(shù)是32位和64位,所謂32位處理器就是一次只能處理32位,也就是4個(gè)字節(jié)的數(shù)據(jù),而64位處理器一次則能處理64位,即8個(gè)字節(jié)的數(shù)據(jù)。

2、一字節(jié)(1Byte)等于8位(8bit),位是計(jì)算機(jī)存儲(chǔ)數(shù)據(jù)的最小單位,也就是計(jì)算存儲(chǔ)的數(shù)據(jù)是一系列二進(jìn)制位信息。每個(gè)位用0或1表示。(大B和小b的區(qū)別需注意哦)

3、為什么一個(gè)字節(jié)是8位?
現(xiàn)在通用的說(shuō)法是8位可以涵蓋所有的字符編碼,即ASCII編碼。但歷史上也存在過4位或者7位為1Byte的場(chǎng)景,只是在后續(xù)的字符集標(biāo)準(zhǔn)統(tǒng)一中逐漸被8bit所替代。除了歷史原因之外,還有數(shù)據(jù)存儲(chǔ)的需要(必須要能在一個(gè)字節(jié)內(nèi)表示超過100種狀態(tài),包括常用數(shù)字,大小寫字母等),再加上早期計(jì)算機(jī)存儲(chǔ)價(jià)格昂貴,所以8bit也是在當(dāng)時(shí)符合二進(jìn)制特性的必然結(jié)果。

4、二進(jìn)制加減運(yùn)算,加法:0+0=0,0+1=1,1+0=1,1+1=10 ,逢2進(jìn)1。

5、二進(jìn)制轉(zhuǎn)十進(jìn)制及十進(jìn)制轉(zhuǎn)二進(jìn)制。

上述列出了一些基本概念和對(duì)應(yīng)的可參考鏈接,建議先優(yōu)先了解一下。尤其是二進(jìn)制和十進(jìn)制的互相轉(zhuǎn)換以及二進(jìn)制的加減法規(guī)則,在后面都會(huì)具體涉及到。

機(jī)器數(shù)、真值

人類用十進(jìn)制完全是因?yàn)槲覀冇?0個(gè)手指頭。如果有一天你看到一個(gè)外星人,它只有4個(gè)手指頭,那么他使用的一定是四進(jìn)制,如圖所示:

我們必須要了解的Java位運(yùn)算(不僅限于Java)

 

如果能看明白上圖,說(shuō)明你已經(jīng)明白了進(jìn)制和手指頭的關(guān)系了。現(xiàn)代的計(jì)算機(jī)內(nèi)部使用門電路,它們只能表示0或者1兩個(gè)狀態(tài)。如果計(jì)算機(jī)是一個(gè)人,那么他只有兩個(gè)手指頭,所以它使用二進(jìn)制。
是的,就是這樣,所謂的進(jìn)制,實(shí)際上并不是什么神秘的東西,只是關(guān)于數(shù)的一種表示方式而已了。門電路概念

機(jī)器數(shù)

機(jī)器數(shù)分為:無(wú)符號(hào)數(shù)和有符號(hào)數(shù)兩種。

一個(gè)數(shù)在計(jì)算機(jī)中的二進(jìn)制表示形式, 叫做這個(gè)數(shù)的機(jī)器數(shù)。機(jī)器數(shù)是帶符號(hào)的,在計(jì)算機(jī)用一個(gè)數(shù)的最高位存放符號(hào), 正數(shù)為0,負(fù)數(shù)為1。

比如,十進(jìn)制中的數(shù) +3 ,計(jì)算機(jī)字長(zhǎng)為8位,轉(zhuǎn)換成二進(jìn)制就是00000011。

如果是 -3 ,就是 10000011 。那么,這里的 00000011 和 10000011 就是機(jī)器數(shù)。

真值

因?yàn)榈谝晃皇欠?hào)位,所以機(jī)器數(shù)的形式值就不等于真正的數(shù)值。

例如上面的有符號(hào)數(shù) 10000011,其最高位1代表負(fù),其真正數(shù)值是 -3 而不是形式值131(10000011轉(zhuǎn)換成十進(jìn)制等于131)。

所以,為區(qū)別起見,將帶符號(hào)位的機(jī)器數(shù)對(duì)應(yīng)的真正數(shù)值稱為機(jī)器數(shù)的真值。

例:0000 0001的真值 = +000 0001 = +1,1000 0001的真值 = –000 0001 = –1

原碼、反碼、補(bǔ)碼

為了妥善的處理數(shù)據(jù)運(yùn)算過程中符號(hào)位的問題,于是就產(chǎn)生了把符號(hào)位和數(shù)值位一起編碼起來(lái)表示相應(yīng)的數(shù)的各種表示方法。例如我們熟悉的原碼、反碼、補(bǔ)碼、移碼等。通常將未經(jīng)編碼的數(shù)稱為真值,編碼后的數(shù)稱為機(jī)器數(shù)或者機(jī)器碼。

計(jì)算機(jī)當(dāng)前所使用的機(jī)器數(shù)是采用的補(bǔ)碼的方式。在探求為何機(jī)器要使用補(bǔ)碼之前, 讓我們先了解原碼, 反碼和補(bǔ)碼的概念。對(duì)于一個(gè)數(shù), 計(jì)算機(jī)要使用一定的編碼方式進(jìn)行存儲(chǔ), 原碼, 反碼, 補(bǔ)碼是機(jī)器存儲(chǔ)一個(gè)具體數(shù)字的編碼方式。

原碼

原碼就是符號(hào)位加上真值的絕對(duì)值, 即用第一位表示符號(hào), 其余位表示值. 比如如果是8位二進(jìn)制:

[+1]原 = 0000 0001
[-1]原 = 1000 0001

第一位是符號(hào)位. 因?yàn)榈谝晃皇欠?hào)位, 所以8位二進(jìn)制數(shù)的取值范圍就是:

[01111111,11111111]

轉(zhuǎn)換為真值后即:

[127,-127 ]

原碼是人腦最容易理解和計(jì)算的表示方式。原碼也可以理解為最原始的機(jī)器碼。

反碼

反碼的表示方法是:
正數(shù)的反碼是其本身,
負(fù)數(shù)的反碼是在其原碼的基礎(chǔ)上, 符號(hào)位不變,其余各個(gè)位取反。

[+1] = [00000001]原 = [00000001]反

[-1] = [10000001]原 = [11111110]反

可見如果一個(gè)反碼表示的是負(fù)數(shù), 人腦無(wú)法直觀的看出來(lái)它的數(shù)值. 通常要將其轉(zhuǎn)換成原碼再計(jì)算。

補(bǔ)碼

補(bǔ)碼的表示方法是:
正數(shù)的補(bǔ)碼就是其本身,
負(fù)數(shù)的補(bǔ)碼是在其原碼的基礎(chǔ)上, 符號(hào)位不變, 其余各位取反, 最后+1. (即在反碼的基礎(chǔ)上+1)。

[+1] = [00000001]原 = [00000001]反 = [00000001]補(bǔ)
[-1] = [10000001]原 = [11111110]反 = [11111111]補(bǔ)

對(duì)于負(fù)數(shù), 補(bǔ)碼表示方式也是人腦無(wú)法直觀看出其數(shù)值的. 通常也需要轉(zhuǎn)換成原碼在計(jì)算其數(shù)值。

互相轉(zhuǎn)換、注意事項(xiàng)

注意:我們?cè)谧畛醯幕靖拍钪刑岬搅硕M(jìn)制和十進(jìn)制的轉(zhuǎn)換方式。但是需要知道的是,一個(gè)數(shù)在計(jì)算機(jī)中的二進(jìn)制表示方式叫做機(jī)器數(shù)。

而機(jī)器數(shù)是有符號(hào)的,我們將對(duì)應(yīng)的最高位存放符號(hào),0位正數(shù),1位負(fù)數(shù)。所以機(jī)器數(shù)并不等于二進(jìn)制。

由此我們才引出了真值的概念,例如:符號(hào)數(shù) 10000011,在十進(jìn)制中對(duì)應(yīng)的值為131,但是在機(jī)器數(shù)中,由于1表示負(fù)數(shù),所以其真正數(shù)值是-3,而并不是131。

符號(hào)數(shù):10000011,我們需要先消除其符號(hào)位的影響,將其調(diào)整為正數(shù):00000011,此時(shí)將正數(shù)轉(zhuǎn)換為10進(jìn)制為3,然后再加上最初的符號(hào)位表示負(fù)數(shù),所以為-3。

需知道的是,二進(jìn)制僅是以2為基數(shù)的計(jì)數(shù)方式而已,在二進(jìn)制中是無(wú)法區(qū)分正數(shù)和負(fù)數(shù)的。而如果想?yún)^(qū)分正數(shù)和負(fù)數(shù)那么必須在二進(jìn)制的最高一位中用0和1來(lái)表示符號(hào)以此來(lái)表示正負(fù)。那么此時(shí)最高位的0和1已經(jīng)不是二進(jìn)制的一種計(jì)數(shù)方式了,而只是一種符號(hào)的標(biāo)識(shí),該符號(hào)的標(biāo)識(shí)則是萬(wàn)萬(wàn)不可以直接參與二進(jìn)制的計(jì)算的。

當(dāng)我們用最高位中的0和1來(lái)表示正負(fù)時(shí),此時(shí)該二進(jìn)制的數(shù)已經(jīng)不再是符合二進(jìn)制規(guī)則的數(shù)了,而是機(jī)器數(shù)。

二進(jìn)制僅僅是以2為基數(shù)的計(jì)算方式,此時(shí)最高位的值已經(jīng)不再是通過2位基數(shù)的計(jì)算方式而計(jì)算出來(lái)的,而只是一個(gè)表示正負(fù)的標(biāo)識(shí)了,所以此時(shí)該數(shù)值則已經(jīng)不再是符合二進(jìn)制規(guī)則的數(shù)了,而是機(jī)器數(shù)。

所以,也只有機(jī)器數(shù)才可以表示正負(fù)。而機(jī)器數(shù)所對(duì)應(yīng)得到的結(jié)果則是真數(shù),而并不是10進(jìn)制數(shù)。

如果此時(shí)拋出來(lái)一個(gè)問題:10000011 轉(zhuǎn)換為對(duì)應(yīng)的10進(jìn)制,那么對(duì)應(yīng)的結(jié)果則是131,但如果是轉(zhuǎn)換為真數(shù),則是-3。同樣的,如果是將00000011 轉(zhuǎn)換為對(duì)應(yīng)的10進(jìn)制,則是3,而如果轉(zhuǎn)換為真數(shù),則也是3。

所以當(dāng)我們看到一個(gè)以8位數(shù)所表示的二進(jìn)制數(shù)時(shí),則一定要確認(rèn)該二進(jìn)制數(shù)是表示機(jī)器數(shù),還是二進(jìn)制數(shù)?是轉(zhuǎn)換為10進(jìn)制數(shù),還是真數(shù)。其中最大的區(qū)別則是,最高的符號(hào)位到底是參與二進(jìn)制的運(yùn)算,還是僅僅表示符號(hào)位。

機(jī)器數(shù)轉(zhuǎn)真數(shù):
10000011 >消除最高位1的影響先轉(zhuǎn)為正數(shù)>00000011>再將該正數(shù)以二進(jìn)制的方式轉(zhuǎn)為十進(jìn)制為> 3 >此時(shí)再將最初的符號(hào)添加回來(lái)>3調(diào)整為-3。

二進(jìn)制數(shù)轉(zhuǎn)10進(jìn)制數(shù):
10000011 >無(wú)需消除最高位1的影響直接轉(zhuǎn)為正數(shù)>10000011>再將該正數(shù)以二進(jìn)制的方式轉(zhuǎn)為十進(jìn)制為 > 131>無(wú)需添加符號(hào)位>131仍然為131。

所以可知,真數(shù)和10進(jìn)制數(shù)最大的區(qū)別則是是否忽略最高位,在確認(rèn)完是否忽略最高位,得到最初的正數(shù)后,該正數(shù)的計(jì)算方式,則和二進(jìn)制轉(zhuǎn)十進(jìn)制的方式完全相同。其實(shí)就是二進(jìn)制轉(zhuǎn)十進(jìn)制。哈哈。


那么在注意了二進(jìn)制數(shù)和機(jī)器數(shù)以及十進(jìn)制數(shù)和真數(shù)的區(qū)別之后。我們則需要注意的另外一個(gè)問題則是:

機(jī)器數(shù)是包含原碼、反碼、補(bǔ)碼。其中三者之間是可以互相轉(zhuǎn)換的。原碼轉(zhuǎn)反碼轉(zhuǎn)補(bǔ)碼,這塊上面已經(jīng)說(shuō)明過了,而補(bǔ)碼則也可以通過想反的方式重新轉(zhuǎn)換為原碼。

而此處需要知曉的則是,反碼和補(bǔ)碼當(dāng)然是不可以直接轉(zhuǎn)為真數(shù)的,而必須要通過原碼才可以進(jìn)行轉(zhuǎn)換。

這個(gè)其實(shí)也沒什么問題,畢竟原碼經(jīng)過層層轉(zhuǎn)換后得到補(bǔ)碼,而補(bǔ)碼又可以直接轉(zhuǎn)換為真數(shù),當(dāng)然不可能了。

接下來(lái)則是,為什么原碼需要轉(zhuǎn)換為補(bǔ)碼,為什么原碼不是計(jì)算機(jī)的計(jì)算方式,而是補(bǔ)碼?

本文原創(chuàng)地址為 https://www.cnblogs.com/zh94/p/16195373.html

原創(chuàng)聲明:作者:陳咬金、 博客地址:https://www.cnblogs.com/zh94/

為什么補(bǔ)碼才是計(jì)算機(jī)的真正計(jì)算方式

現(xiàn)在我們知道了計(jì)算機(jī)可以有三種編碼方式表示一個(gè)數(shù). 對(duì)于正數(shù)因?yàn)槿N編碼方式的結(jié)果都相同:

[+1] = [00000001]原 = [00000001]反 = [00000001]補(bǔ)

所以不需要過多解釋. 但是對(duì)于負(fù)數(shù):

[-1] = [10000001]原 = [11111110]反 = [11111111]補(bǔ)

可見原碼, 反碼和補(bǔ)碼是完全不同的. 既然原碼才是被人腦直接識(shí)別并用于計(jì)算表示方式, 為何還會(huì)有反碼和補(bǔ)碼呢?

首先, 因?yàn)槿四X可以知道第一位是符號(hào)位, 在計(jì)算的時(shí)候我們會(huì)根據(jù)符號(hào)位, 選擇對(duì)真值區(qū)域的加減。
但是對(duì)于計(jì)算機(jī), 加減乘數(shù)已經(jīng)是最基礎(chǔ)的運(yùn)算, 要設(shè)計(jì)的盡量簡(jiǎn)單. 計(jì)算機(jī)辨別"符號(hào)位"顯然會(huì)讓計(jì)算機(jī)的基礎(chǔ)電路設(shè)計(jì)變得十分復(fù)雜! 于是人們想出了將符號(hào)位也參與運(yùn)算的方法. 我們知道, 根據(jù)運(yùn)算法則減去一個(gè)正數(shù)等于加上一個(gè)負(fù)數(shù), 即: 1-1 = 1 + (-1) = 0 , 所以機(jī)器可以只有加法而沒有減法, 這樣計(jì)算機(jī)運(yùn)算的設(shè)計(jì)就更簡(jiǎn)單了。

于是人們開始探索 將符號(hào)位參與運(yùn)算, 并且只保留加法的方法. 首先來(lái)看原碼:
計(jì)算十進(jìn)制的表達(dá)式: 1-1=0

1 - 1 = 1 + (-1) = [00000001]原 + [10000001]原 = [10000010]原 = -2

如果用原碼表示, 讓符號(hào)位也參與計(jì)算, 顯然對(duì)于減法來(lái)說(shuō), 結(jié)果是不正確的.這也就是為何計(jì)算機(jī)內(nèi)部不使用原碼表示一個(gè)數(shù)。
為了解決原碼做減法的問題, 出現(xiàn)了反碼:
計(jì)算十進(jìn)制的表達(dá)式: 1-1=0

1 - 1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原= [0000 0001]反 + [1111 1110]反 = [1111 1111]反 = [1000 0000]原 = -0

發(fā)現(xiàn)用反碼計(jì)算減法, 結(jié)果的真值部分是正確的. 而唯一的問題其實(shí)就出現(xiàn)在"0"這個(gè)特殊的數(shù)值上. 雖然人們理解上+0和-0是一樣的, 但是0帶符號(hào)是沒有任何意義的. 而且會(huì)有[0000 0000]原和[1000 0000]原兩個(gè)編碼表示0。

于是補(bǔ)碼的出現(xiàn), 解決了0的符號(hào)以及兩個(gè)編碼的問題:

1-1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原 = [0000 0001]補(bǔ) + [1111 1111]補(bǔ) = [0000 0000]補(bǔ)=[0000 0000]原

這里說(shuō)明一下,二進(jìn)制想加:0000 0001+1111 1111 = 1 0000 0000,但由于是8位數(shù),所以最終的值為 0000 0000。

這樣0用[0000 0000]表示, 而以前出現(xiàn)問題的-0則不存在了.而且可以用[1000 0000]表示-128:

(-1) + (-127) = [1000 0001]原 + [1111 1111]原 = [1111 1111]補(bǔ) + [1000 0001]補(bǔ) = [1000 0000]補(bǔ)

由于我們使用原碼來(lái)表示正時(shí),最大值為:01111111,最小值為:11111111,所以直接轉(zhuǎn)換為對(duì)應(yīng)的10進(jìn)制后的結(jié)果為,127,-127。
而此處使用補(bǔ)碼后,由于補(bǔ)碼的規(guī)則是,首位不變,其它反轉(zhuǎn),并+1。所以(-1)+(-127) 剛好為-128。

使用補(bǔ)碼, 不僅僅修復(fù)了0的符號(hào)以及存在兩個(gè)編碼的問題, 而且還能夠多表示一個(gè)最低數(shù). 這就是為什么8位二進(jìn)制, 使用原碼或反碼表示的范圍為[-127, +127], 而使用補(bǔ)碼表示的范圍為[-128, 127]。

因?yàn)闄C(jī)器使用補(bǔ)碼, 所以對(duì)于編程中常用到的32位int類型, 可以表示范圍是: [-2的31次方, 2的31次方 - 1] 因?yàn)榈谝晃槐硎镜氖欠?hào)位.而使用補(bǔ)碼表示時(shí)又可以多保存一個(gè)最小值。

Amazing,我們?cè)谏厦孀畛跏褂迷a進(jìn)行加法運(yùn)算時(shí),由于我們?nèi)四X還需要先判斷一下最高位的符號(hào)后,才能進(jìn)行二進(jìn)制運(yùn)算,然后再添加上對(duì)應(yīng)的符號(hào)位。而采用補(bǔ)碼后,直接將對(duì)應(yīng)的符號(hào)位也參與運(yùn)算,將補(bǔ)碼的數(shù)值直接相加,得到的竟然剛好也就是二進(jìn)制轉(zhuǎn)換后的結(jié)果。這樣一來(lái),計(jì)算機(jī)的基礎(chǔ)電路設(shè)計(jì)就可以更加簡(jiǎn)單,而無(wú)需關(guān)注符號(hào)位的問題,僅需要按照二進(jìn)制的加法法則執(zhí)行即可。簡(jiǎn)直完美。所以這也是補(bǔ)碼作為計(jì)算機(jī)的真正計(jì)算方式的原因之一!

但,補(bǔ)碼后所得到的值想加剛好就是直接二進(jìn)制的值相加后的結(jié)果,真的是就剛好這么巧嗎?其實(shí)不然,背后還蘊(yùn)含這很有意思的數(shù)學(xué)原理,詳情可參考:
深入理解原碼、補(bǔ)碼 & 數(shù)的機(jī)器碼表示 & 機(jī)器碼原理 & 原碼、補(bǔ)碼原理

位運(yùn)算

文章最頂部基本概念處列到了“10進(jìn)制2進(jìn)制互轉(zhuǎn)”,以及“2進(jìn)制加減法”對(duì)應(yīng)的相關(guān)鏈接。
此處再推薦幾個(gè)在線計(jì)算的網(wǎng)址,便于將自己的計(jì)算結(jié)果進(jìn)行二次驗(yàn)證:
在線原碼、補(bǔ)碼、10進(jìn)制互轉(zhuǎn) & 在線進(jìn)制轉(zhuǎn)換 & 在線二進(jìn)制加減法

接下來(lái)則開始涉及到位運(yùn)算了。

概念

什么是位運(yùn)算?我們先來(lái)看下百度百科的概念:

程序中的所有數(shù)在計(jì)算機(jī)內(nèi)存中都是以二進(jìn)制的形式儲(chǔ)存的。位運(yùn)算就是直接對(duì)整數(shù)在內(nèi)存中的二進(jìn)制位進(jìn)行操作。

百度百科中所給的解釋是具備歧義性的,按照百度百科的解釋,直接對(duì)整數(shù)在內(nèi)存中的二進(jìn)制位進(jìn)行操作就是位運(yùn)算的話,那么使用二進(jìn)制數(shù)進(jìn)行算術(shù)運(yùn)算法(+,-,*,/ )豈不是也屬于位運(yùn)算?

我們?cè)賮?lái)看下維基百科所給的概念解釋:

位操作是程序設(shè)計(jì)中對(duì)位模式或二進(jìn)制數(shù)的一元和二元操作。在許多古老的微處理器上,位運(yùn)算比加減運(yùn)算略快,通常位運(yùn)算比乘除法運(yùn)算要快很多。在現(xiàn)代架構(gòu)中,情況并非如此:位運(yùn)算的運(yùn)算速度通常與加法運(yùn)算相同(仍然快于乘法運(yùn)算)。

維基百科中針對(duì)位運(yùn)算的概念相對(duì)合理,通過維基百科中的概念我們可以很明顯的區(qū)分到,位運(yùn)算是和加減乘除這些算數(shù)運(yùn)算符是不同的。不同的CPU針對(duì)位運(yùn)算的操作是較快于(乘/除)法運(yùn)算的。

所以這也才是我們需要了解位運(yùn)算的真正原因,那就是CPU處理器針對(duì)位運(yùn)算符的計(jì)算是快于算術(shù)運(yùn)算符的!在特定的編碼場(chǎng)景下使用位運(yùn)算的執(zhí)行速率則是遠(yuǎn)遠(yuǎn)大于算術(shù)運(yùn)算的!

網(wǎng)絡(luò)上針對(duì)位運(yùn)算較多的內(nèi)容解釋是:位運(yùn)算是直接對(duì)整數(shù)在內(nèi)存中的二進(jìn)制位進(jìn)行操作,所以位運(yùn)算更加節(jié)省內(nèi)存、提高運(yùn)算效率等等的。其實(shí)這是很不嚴(yán)謹(jǐn)?shù)恼f(shuō)法,很容易誤導(dǎo)大家對(duì)位運(yùn)算的理解,因?yàn)樗械恼麛?shù)最終在計(jì)算機(jī)中都是二進(jìn)制數(shù),那么所有對(duì)整數(shù)的運(yùn)算豈不是都是位運(yùn)算?當(dāng)然不是啦。且,位運(yùn)算真正快的原因也并不是因?yàn)楣?jié)省內(nèi)存,而主要是因?yàn)镃PU對(duì)位運(yùn)算的支持!和內(nèi)存并沒有較大關(guān)聯(lián)。

為何位運(yùn)算CPU執(zhí)行速率更快

程序中的基本運(yùn)算包含:

  • 算術(shù)運(yùn)算:加、減、乘、除、取余
  • 按位運(yùn)算:按位或“|”、按位與“&”、按位取反“~”、按位異或“^”
  • 移位運(yùn)算:左移x<<k;右移x>>k

其中按位運(yùn)算和移位運(yùn)算均屬于位運(yùn)算的范疇。

位運(yùn)算的具體執(zhí)行邏輯,我們下面會(huì)詳細(xì)說(shuō)明。這里先以位運(yùn)算中的 與 運(yùn)算符 “&” 來(lái)簡(jiǎn)單說(shuō)明下位運(yùn)算的主要執(zhí)行邏輯:
& 與運(yùn)算符的運(yùn)算規(guī)則是:兩個(gè)位都為1時(shí),則結(jié)果為1。如:3&5 即 0000 0011& 0000 0101 = 0000 0001,因此 3&5 的值得1。

根據(jù)與運(yùn)算符的規(guī)則可知,位運(yùn)算的整體執(zhí)行邏輯實(shí)際是較為簡(jiǎn)單的,更多的是進(jìn)行位數(shù)的比較,從而得到一個(gè)結(jié)果,這種較為簡(jiǎn)單的運(yùn)算邏輯,則對(duì)于CPU處理器來(lái)說(shuō),在電路的設(shè)計(jì)中則也會(huì)更加簡(jiǎn)單許多,以下為與運(yùn)算符所涉及到的CPU電路圖:

我們必須要了解的Java位運(yùn)算(不僅限于Java)

 

而對(duì)于一個(gè)除法來(lái)說(shuō)呢,在CPU中所對(duì)應(yīng)的電路圖設(shè)計(jì)則是這樣的:

我們必須要了解的Java位運(yùn)算(不僅限于Java)

 

可以看到,整個(gè)CPU電路圖的設(shè)計(jì)復(fù)雜了不止一個(gè)層級(jí),所以這也就是為何位運(yùn)算比我們?nèi)顺S玫乃阈g(shù)運(yùn)算更快的直接原因了。因?yàn)閷?duì)于整個(gè)CPU的執(zhí)行邏輯來(lái)說(shuō)從設(shè)計(jì)層面就復(fù)雜了很多。


當(dāng)然,提到CPU的電路圖設(shè)計(jì),就不得不提到對(duì)應(yīng)的CPU中晶體管的特性了,而晶體管中所涉及到的開關(guān)(01)的特性也就構(gòu)成了邏輯電路,從而構(gòu)成了與門、或門、非門、異或門等電路特性。
這塊內(nèi)容,可以參考如下鏈接:
位運(yùn)算中隱藏的CPU秘密
程序中的位運(yùn)算于基本電路關(guān)系
程序中位運(yùn)算于基本電路-知乎
四位計(jì)算機(jī)的原理及實(shí)現(xiàn)
位運(yùn)算的理解
程序中的取余是如何實(shí)現(xiàn)的
二進(jìn)制乘除法的實(shí)現(xiàn)

CPU中的電路設(shè)計(jì)和數(shù)學(xué)的算法實(shí)現(xiàn)有著很精妙的聯(lián)系,計(jì)算機(jī)前輩的力量是無(wú)窮的。那到了這里,我們也就知道了程序中基本運(yùn)算在執(zhí)行速率上的真正差別實(shí)際上是在CPU這一層級(jí)的,了解了這些之后,我們也就可以接著開始說(shuō)明位運(yùn)算符的真正執(zhí)行邏輯了。
(位運(yùn)算僅需進(jìn)行01的比較,和移位等簡(jiǎn)單的邏輯操作,基本上和直接執(zhí)行二進(jìn)制的相加規(guī)則一樣,在電路設(shè)計(jì)和邏輯上均更加簡(jiǎn)單,而乘除求余則在電路的設(shè)計(jì)中較為復(fù)雜)

本文原創(chuàng)地址為 https://www.cnblogs.com/zh94/p/16195373.html

原創(chuàng)聲明:作者:陳咬金、 博客地址:https://www.cnblogs.com/zh94/

位運(yùn)算符

首先需知道的是,計(jì)算機(jī)中執(zhí)行位運(yùn)算,肯定是采用的補(bǔ)碼的方式進(jìn)行的位計(jì)算哦,所以對(duì)于真值為負(fù)數(shù)的情況下,必須先轉(zhuǎn)為補(bǔ)碼才能進(jìn)行計(jì)算。

符號(hào)

描述

運(yùn)算規(guī)則

&

兩個(gè)位都為1時(shí),結(jié)果才為1

|

兩個(gè)位都為0時(shí),結(jié)果才為0

^

異或

兩個(gè)位相同為0,相異為1

~

取反

0變1,1變0

<<

左移

各二進(jìn)位全部左移若干位,高位丟棄,低位補(bǔ)0

>>

右移

各二進(jìn)位全部右移若干位,對(duì)無(wú)符號(hào)數(shù),高位補(bǔ)0。各編譯器處理方法不一樣,有的補(bǔ)符號(hào)位(算術(shù)右移),有的補(bǔ)0(邏輯右移)

& 與運(yùn)算符

運(yùn)算規(guī)則:兩位同時(shí)為1,結(jié)果才為1,否則結(jié)果為0。

0&0=0  0&1=0  1&0=0  1&1=1

例如:2 & -2

我們必須要了解的Java位運(yùn)算(不僅限于Java)

 

注意:負(fù)數(shù)當(dāng)然是按照補(bǔ)碼的方式來(lái)進(jìn)行位計(jì)算哦。

& 與運(yùn)算符的用途:

根據(jù)與運(yùn)算符的計(jì)算特性,我們常用的使用方式有:
1、判斷奇偶數(shù)
我們知道,按照二進(jìn)制和十進(jìn)制(除二取余)的換算方式,如果是偶數(shù)的情況下,換算為二進(jìn)制后末位必然是0,如果是奇數(shù)則末位為1。比如:2 >10 ,3 > 11,100 >1100100,121 > 1111001。

所以,我們按照與運(yùn)算符的運(yùn)算規(guī)則,使用 if(a & 1)1表示為奇數(shù),if(a & 1)0,則表示為偶數(shù)。
如:
121 & 1 = 1111001 & 0000001 = 0000001
2 & 1 =10 & 01 =00

使用與運(yùn)算符的方式,則完全可以替代掉:if (a % 2 == 0) 來(lái)判斷奇偶數(shù)的方式,且位運(yùn)算符由于CPU的支持,執(zhí)行效率也更高。

關(guān)于二進(jìn)制轉(zhuǎn)十進(jìn)制的方式,參考基本概念中URL即可。

2、取一個(gè)數(shù)的指定位
比如取數(shù) X=1010 1110 高4位,只需要另外找一個(gè)數(shù),令 Y的高4位為1,其余位為0,即Y=1111 0000,然后將X和Y進(jìn)行與運(yùn)算,(X & Y = 1010 1110 & 1111 0000 = 1010 0000)即可得到X 的指定高4位。

如果想獲取X的低4位的數(shù),則將Y的低4位為1,其余位數(shù)為0即可,(X & Y=1010 1110 & 0000 1111=0000 1110)便可得到X的指定低4位。

| 或 運(yùn)算符

運(yùn)算規(guī)則:兩個(gè)位都為0時(shí),則結(jié)果為0。否則則為1。

0|0=0  0|1=1  1|0=1  1|1=1

例如:2 | -2 =-2

我們必須要了解的Java位運(yùn)算(不僅限于Java)

 

| 或運(yùn)算符的用途

首先與和或是兩個(gè)相反的概念,所以上述所提到的與的用途,在這里只要略作改造就也適合于或運(yùn)算符。但是
目的是一樣的,所以對(duì)應(yīng)相同用途的場(chǎng)景,這里不再贅述。

1、常用來(lái)對(duì)一個(gè)數(shù)據(jù)的某些位設(shè)置為1
比如將數(shù) X=1010 1110 的低4位設(shè)置為1,只需要另找一個(gè)數(shù)Y,令Y的低4位為1,其余位為0,即Y=0000 1111,然后將X與Y進(jìn)行按位或運(yùn)算(X|Y=1010 1111)即可得到。

同樣的,使用 & 運(yùn)算符,則可以方便的將某些位設(shè)置為 0,如上述的X & Y,將X的低4位設(shè)置為0,則
X & Y = 1010 1110 & 1111 0000 = 1010 0000。

以上則說(shuō)明 & 和 | 靈活運(yùn)用,其實(shí)是可以達(dá)到相同效果的。但實(shí)際使用中則并不然,首先對(duì)于上述低4位設(shè)置為1的場(chǎng)景,我們只需要找一個(gè)Y的數(shù),令Y的低4位為1,其余位為0,這樣一個(gè)數(shù)是很好找的,是一個(gè)固定的數(shù),比如:15。轉(zhuǎn)換為二進(jìn)制后為1111。

但如果使用 & 運(yùn)算符來(lái)面對(duì)這個(gè)場(chǎng)景,則需要找一個(gè)Y,Y的第四位為0,其余位置為1,這樣一個(gè)數(shù)則很難找,并且隨著位數(shù)的不同,值也是不斷變換的,比如:1111 0000=240,但如果是12位數(shù),1111 1111 0000=4080。所以如果使用 & 運(yùn)算符來(lái)在該場(chǎng)景下則是沒有 | 運(yùn)算符更加方便的。

盡管 & 和 | 的規(guī)則相反,可靈活變更,但針對(duì)特定場(chǎng)景下,還是使用特定的運(yùn)算符效果更佳O。

^ 異或運(yùn)算符

運(yùn)算規(guī)則:兩個(gè)位相同為0,相異為1。

0^0=0  0^1=1  1^0=1  1^1=0

例如:2 ^ -2

我們必須要了解的Java位運(yùn)算(不僅限于Java)

 

^ 異或運(yùn)算符用途

1、交換兩個(gè)數(shù)

a=a^b;      //a=a^b
b=a^b;      //b=(a^b)^b=a^0=a
a=a^b;      //a=(a^b)^(a^b^b)=0^b=0

交換兩個(gè)數(shù)的原理,即上面注釋所寫內(nèi)容。

不使用位運(yùn)算的方式交換兩個(gè)數(shù),則需要定義一個(gè)中間變量C,來(lái)承接其中的一個(gè)數(shù)的交換,對(duì)于JAVA來(lái)說(shuō),定義一個(gè)新的Int 變量C,則表示內(nèi)存中需開辟一個(gè)4字節(jié)的空間。

所以根據(jù)服務(wù)特性來(lái)選擇合適的方式即可,對(duì)內(nèi)存使用率有強(qiáng)要求則使用位運(yùn)算,沒要求則都可以。

static void swap(int a, int b) {    int c = a;    a = b;    b = c;}

static void swapBit(int a, int b) {    a = a ^ b;    b = a ^ b;    a = a ^ b;}

~ 取反運(yùn)算符

運(yùn)算規(guī)則:0變1,1變0。

我們必須要了解的Java位運(yùn)算(不僅限于Java)

 

<< 左移運(yùn)算符

運(yùn)算規(guī)則:將一個(gè)運(yùn)算對(duì)象的各二進(jìn)制位全部左移若干位(左邊的二進(jìn)制位丟棄,右邊補(bǔ)0)。

設(shè) a=15,即二進(jìn)制數(shù)00001111,左移2位得00111100,即十進(jìn)制數(shù)60。

左移一位相當(dāng)于該數(shù)乘以2,左移2位相當(dāng)于該數(shù)乘以2^2=4。上面舉的例子15<< 2=60,即乘了4。
(結(jié)論:左移n位等于乘以2的n次方)

設(shè) a=-46,補(bǔ)碼后為,1010 1110,a = a<< 2 將a的二進(jìn)制位左移2位、右補(bǔ)0,即得a=1011 1000,轉(zhuǎn)換為真值后為-56。

設(shè) a=110,補(bǔ)碼后為:0110 1110,a = a<<2 將a 的二進(jìn)制位左移2位,右補(bǔ)0,即得 a=1011 1000,轉(zhuǎn)換為真值后為184。

以此可知,左移n位等于乘以2的n次方,該結(jié)論僅適用于該數(shù)左移時(shí)被溢出舍棄的高位中不包含1的情況,如果溢出的高位中包含1,則不符合上述結(jié)論。

>> 右移運(yùn)算符

運(yùn)算規(guī)則:將一個(gè)數(shù)的各二進(jìn)制位全部右移若干位,正數(shù)左補(bǔ)0,負(fù)數(shù)左補(bǔ)1,右邊丟棄。
例如:a=a>>2 將a的二進(jìn)制位右移2位,左補(bǔ)0 或者 左補(bǔ)1需要看被移數(shù)是正還是負(fù)。

設(shè) a=16,補(bǔ)碼后為00010000,a = a<<2 將a的二進(jìn)制位右移2位,左邊補(bǔ)0,即得a=00000100,轉(zhuǎn)換為真值后為4。

設(shè)a=-16,補(bǔ)碼后為11110000,a = a<<2 將a的二進(jìn)制位右移2位,左邊補(bǔ)1,得到a=11111100,轉(zhuǎn)換真值后為-4。

結(jié)論:右移運(yùn)算符,操作數(shù)每右移一位,相當(dāng)于該數(shù)除以2。

本文原創(chuàng)地址為 https://www.cnblogs.com/zh94/p/16195373.html

原創(chuàng)聲明:作者:陳咬金、 博客地址:https://www.cnblogs.com/zh94/

Java位運(yùn)算

位運(yùn)算本身就是處理器、計(jì)算機(jī)自身所提供的能力,所以針對(duì)位運(yùn)算的使用,實(shí)際上是不限于任何編程語(yǔ)言的,此處之所以以JAVA為例,主要是因?yàn)楸救顺S玫拈_發(fā)語(yǔ)言是JAVA,哈哈。

針對(duì)JAVA中位運(yùn)算的使用,實(shí)際上在JDK中有這很豐富的案例,比如:

1、JDK中線程池ThreadPoolExecutor的實(shí)現(xiàn)當(dāng)中使用Integer類型(4字節(jié),32位)其中高3位保存線程池狀態(tài),而低29位保存線程池內(nèi)有效線程數(shù)量。

2、比如JDK的HashMap中使用位運(yùn)算的方式將初始化容量的數(shù)值,快速的轉(zhuǎn)換為2的n次冪。以及計(jì)算key的hash時(shí),根據(jù)該key的hashCode結(jié)果,再將該hashCode的高16位和低16位通過位運(yùn)算的方式進(jìn)行混合,以此降低hash碰撞的概率等等。

3、比如我們直接打開常用的Integer類的源碼,也會(huì)發(fā)現(xiàn)里面有大量的位運(yùn)算的使用。

此處僅是為了通過上述舉例的方式來(lái)以此說(shuō)明位運(yùn)算在Java生態(tài)中的使用程度,實(shí)際上是非常豐富的,并且由于位運(yùn)算獨(dú)特的計(jì)算特性,在某些相對(duì)特殊的代碼場(chǎng)景下,使用位運(yùn)算會(huì)意想不到的將問題給簡(jiǎn)單化。

如果想了解更多在JAVA中的使用場(chǎng)景和案例,建議大家直接翻看各種源碼即可。

以上是一些舉例,以下再做一些小的補(bǔ)充說(shuō)明:

在Java當(dāng)中的位運(yùn)算,是只針對(duì)Int類型和Long類型有效(java中,一個(gè)int的長(zhǎng)度始終是32位,也就是4個(gè)字節(jié),它操作的都是該整數(shù)的二進(jìn)制數(shù),Long則是64位,表示8字節(jié)。),而對(duì)于byte,char,short,當(dāng)為這三個(gè)類型時(shí),JVM會(huì)先把他們轉(zhuǎn)換為Int類型后再進(jìn)行操作。

使用 toBinaryString() 可以將對(duì)應(yīng)的十進(jìn)制轉(zhuǎn)為對(duì)應(yīng)的補(bǔ)碼。

System.out.println(Integer.toBinaryString(10));//1010
System.out.println(Integer.toBinaryString(-10));//11111111111111111111111111111101
System.out.println(Long.toBinaryString(10));//1010
System.out.println(Long.toBinaryString(-10));//1111111111111111111111111111111111111111111111111111111111110110

如上代碼可知,Integer和Long轉(zhuǎn)換為補(bǔ)碼時(shí),Integer為32位,Long是64位。實(shí)際上上述的基本類型32位還是64位,均是直接定義在源碼當(dāng)中的,感興趣直接看對(duì)應(yīng)的Integer和Long的源碼即可。

其它參考鏈接

以下參考鏈接,僅供參考,部分鏈接中的內(nèi)容,可能會(huì)具備一些歧義,請(qǐng)讀者自行分辨。

祝福各位讀者所有看到的知識(shí),都可以最終成為自己的知識(shí)!撒花!??ヽ(°▽°)ノ?!

位運(yùn)算教程
位運(yùn)算介紹
java位運(yùn)算
位運(yùn)算技巧
位運(yùn)算常用方式

分享到:
標(biāo)簽:運(yùn)算 Java
用戶無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定