爲了更好的讀源碼,你必須搞定這些java基礎知識!(位運算,進制轉換和原碼,反碼和補碼)

不知道上一篇文章看的怎麼樣了:懼怕面試被問HashMap?這一篇就搞定了!
在這篇文章中,我比較詳細的分析了爲何HashMap的初始化容量是16以及爲何容量的大小要是2的整數次冪!java

不知道你看懂了沒,若是你看的懵懵懂懂的話,我猜你對如下基礎知識必定不那麼熟悉:web

  1. java中的位運算
  2. 進制之間的轉換
  3. 原碼,反碼和補碼

怎麼樣,對這些基礎知識掌握的如何,這些能夠說都是大學時候學的計算機基礎了,不過,我知道你當時確定沒學會,即便學會了也忘得差很少了。面試

其實吧,這些基礎知識真的超級重要,你看,如今閱讀源碼的時候由於這些基礎知識不過關而遇到坎了吧。算法

別擔憂,今天我們一塊兒越過這道坎!數據結構

先從進制轉換開始

對於進制轉換這個啊,說來慚愧,我以前學過不止一次,曾經有一次還花了很長時間,作筆記,畫圖,弄了滿滿的一張A4紙,當時以爲對進制轉換這塊徹底OK了,之後不再怕進制轉換了。併發

但是嘞後來讀源碼的時候遇到進制轉換的時候仍是以爲不知所措,發現以前學的都忘得差很少了,唉。app

因此啊,對於學習,咱們可不能一味的向前學習新知識,對於以前的知識也要常常回顧,溫故而知新,能夠爲師矣嘛工具

好啦,我們此次再來一塊兒學習下進制轉換吧!學習

對於進制轉換啊,其實咱們的重點主要放在與十進制之間的各類轉換便可,由於這纔是咱們日常使用頻率比較高的,因此要優先熟練的掌握這些。網站

啥是二進制

十進制咱們再熟悉不過了,那啥是二進制嘞,簡單來講,二進制就是用0和1來表示的數值,在十進制中逢十進一,借一當十,而二進制呢?那就是逢二進一,借一當二,這個好懂,可是這裏我要說些概念。

什麼嘞?後面咱們要說到原碼,反碼和補碼,這裏先說下,它們都是二進制數,也就是都是由0和1表示的,單是可能具體的數值不同。

咱們要知道,對於計算機而言,它只認識0和1,因此對於數據在計算機中的存儲都是以二進制的形式來存儲的,好了,先有這個概念。

十進制與二進制之間的一個規律

先來看一個圖:

在這裏插入圖片描述
在這裏插入圖片描述

不知道你看出來什麼沒,主要看標紅的,前面說過了,二進制就是逢二進一,那麼上圖中標紅的二進制是否是都是產生進位的數值,啥意思嘞,好比二進制11,並無產生進位,若是要產生進位,那就要再加一,而後就會產生進位得100,你看是否是?

再看進位產生的二進制對應的十進制是否是這些數值:

2,4,8,16……

那麼你看這些產生進位的二進制數值有什麼特色,是否是最高位(最左邊)是否是都是1,其餘都是0,因此這裏就有個規律:

十進制下的2的整數次冪的數的二進制的高位都是1,其餘全是0,而後看是2的幾回冪,是幾就有幾個零

好吧,我相信這裏沒什麼難理解的!

ps:看到這裏你是否是更容易理解爲何HashMap的容量要是2的整數次冪了呢?

二進制轉十進制

那麼二進制的數據怎麼轉換成十進制呢?咱們看十進制的11從右往左是否是依次表明1個1,1個10,加起來也就是11.

那麼來看二進制1011怎麼表示,看下面的:

二進制的數從右向左各個位表示十進制的含義:

第一個1表示:1的個數(有1個1)
第二個1表示:2的個數(有1個2)
第三個0表示:4的個數(有0個4)
第四個1表示:8的個數(有1個8)

爲何是1(默認右邊第一位開始),2,4,8呢?注意上面說的那個規律,因此上面的加起來就是1+2+0+8等於11。

怎麼樣?二進制轉十進制是否是比較簡單,其實後面還有個公式,等下再說,咱們繼續往下看

十進制轉二進制

知道嗎?這裏有個通用的方法那就是:除以2,餘數逆序排列,看個例子吧:

在這裏插入圖片描述
在這裏插入圖片描述

也就是說十進制轉換成二進制的話,那就用十進制的數除以2,而後取餘數以後將餘數逆序排列就是對應的二進制數了,怎麼樣是否是更簡單,咱們接着往下看

十進制與其餘進制之間的轉換

咱們以前就說過,對於進制轉換咱們重點關注的就是與十進制之間的轉換,咱們上面介紹了二進制和十進制之間的互相轉換,那麼還有八進制和十六進制,它們與十進制之間的轉換又是怎樣呢?

這裏首先記住十進制轉換其餘進制的通用方法:

「除基數B取餘,逆序排列」方法能夠將十進制數轉換爲任意進制數。

那麼這個基數B是啥呢?好比十進制轉換成二進制,那麼這個基數B就是2,知道了吧!

那麼其餘進制轉換成十進制怎麼整嘞?記住這個公式:

在這裏插入圖片描述
在這裏插入圖片描述

這個公式能夠歸納爲:「按權展開」—其餘進制轉換爲十進制(B表示各進制的基數,n表示位數)

舉個例子,好比以前1011這個二進制轉換成十進制就能夠這樣:

在這裏插入圖片描述
在這裏插入圖片描述

就是這樣的啦,至於其餘的什麼八進制和十六進制之間的互相轉換什麼的,不怎麼經常使用,感興趣的自行了解,對了,我日常都是直接搜索在線進制轉換的😂

進攻位運算

瞭解了進制轉換,尤爲是十進制和二進制之間的轉換以後咱們就能夠開始學習java中的位運算了,由於位運算實際上都是對二進制進行操做的,接下來我將逐步分析java中常見的位運算。

左移 <<

舉個栗子,5 << 2 將5左移2 結果爲20 爲啥?注意是對二進制進行的操做,來看:

首先會將5轉爲二進制表示形式(java中,整數默認就是int類型,也就是32位):

在這裏插入圖片描述
在這裏插入圖片描述

怎麼去理解,首先在Java中,整數默認就是int類型,也就是佔4個字節32位,你就能夠想成這樣

0000 0000 0000 0000 0000 0000 0000 0000

這就是32位,可是每位上都是0,這是一個標準,用於後面的比較,好比5的二進制是

0000 0000 0000 0000 0000 0000 0000 0101

而後把它與標準的進行對比,也就是這樣:

在這裏插入圖片描述
在這裏插入圖片描述

這時候的區別就在後四位,而後將5左移(<<)2,也就是5的二進制以標準爲參考總體左移2位,也就是這樣:

在這裏插入圖片描述
在這裏插入圖片描述

這樣一來,就產生了錯位,看圖:
在這裏插入圖片描述
在這裏插入圖片描述

不過這時候看着老是有點彆扭,應該都是四位四位的在一塊吧,因此從低位開始,四位一組,就成了這樣
0000 0000 0000 0000 0000 0000 0001 0100

換算成十進制就是20了 這就是5 << 2獲得結果的由來。

右移 >>

仍是先將5轉爲2進製表示形式:
0000 0000 0000 0000 0000 0000 0000 0101 而後右移2位,高位補0:
0000 0000 0000 0000 0000 0000 0000 0001

看圖:

在這裏插入圖片描述
在這裏插入圖片描述

仔細看圖分析分析😃

無符號右移 >>>

先記住這句話:正數右移,高位補0,負數右移,高位補1,負數無符號右移,高位補0 正數無符號右移 ,高位補0 正數換算成二進制後的最高位爲0,負數的二進制最高位爲1

接下來依然是看例子,在此以前我看過好多別人寫的,發現好多都喜歡用5舉例子你知道爲啥嗎😂

5換算成二進制是: 0000 0000 0000 0000 0000 0000 0000 0101

5右移3位後結果爲0,0的二進制爲: 0000 0000 0000 0000 0000 0000 0000 0000 // (這裏高位補0)

-5換算成二進制是: 1111 1111 1111 1111 1111 1111 1111 1011

-5右移3位後結果爲-1,-1的二進制爲: 1111 1111 1111 1111 1111 1111 1111 1111 // (高位補1)

-5無符號右移3位後的結果 536870911 換算成二進制: 0001 1111 1111 1111 1111 1111 1111 1111 // (高位補0)

這裏須要注意了:以上說的都是右移的狀況,若是是左移,不管是正數仍是負數,低位都是用0補

時間關係,就不贅述了。

位與 &

其實核心都是二進制,因此掌握好進制轉換是關鍵,看看位與 &是怎麼計算的:

在這裏插入圖片描述
在這裏插入圖片描述

這裏要看兩個操做數的二進制的各個位的對應狀況,總結起來也就是:

有0則0,不然爲1

什麼意思呢?咱們舉一個例子來看看

在這裏插入圖片描述
在這裏插入圖片描述

咱們猜這個結果是什麼,答案是

在這裏插入圖片描述
在這裏插入圖片描述

注意這裏可不是6除以3,它是這樣計算的,首先6和3都要轉成二進制,6的二進制是110,3的二進制是11也就是011,那麼這樣運算

在這裏插入圖片描述
在這裏插入圖片描述

我相信看圖就能明白的,而二進制的010就是2啦,這就是位與的操做,對於或和亦或其實一樣道理,咱們繼續來看:

位或 |

規則就是:有1則1

看例子:

在這裏插入圖片描述
在這裏插入圖片描述

位異或 ^

規則是:相同則0,不一樣則1

看例子:

在這裏插入圖片描述
在這裏插入圖片描述

有點難懂的位非 ~

這是網站隨便找的一個例子,你看看,求~5,得-6,爲啥?

在這裏插入圖片描述
在這裏插入圖片描述

它這裏的規則是:操做數的第n位爲1,那麼結果的第n位爲0,反之。

不知道你懂嗎?有這麼一個解釋:

6的二進制數爲: 0000 0000 0000 0000 0000 0000 0000 0110 而後6的二進制反碼爲: 1111 1111 1111 1111 1111 1111 1111 1001 將反碼+1獲得-6的補碼二進制數:1111 1111 1111 1111 1111 1111 1111 1010

因此這裏就牽涉到原碼,反碼和補碼了,另外還有個重點的點就是:

負數在計算機中是以補碼的形式存在的

好了,咱們趕忙來看看什麼是原碼,反碼和補碼吧!

最後攻克原碼,反碼和補碼

這是很是重要的概念,須要熟練掌握,要記得。開始以前,先上一個重要的結論:

數據在計算機中的存儲是二進制的形式,二進制簡單來講就是0和1組合的,不管原碼,反碼仍是補碼,都是二進制的形式

其次咱們要注意的點就是正數和負數的原碼,反碼和補碼,是有區別的。

原碼

什麼是原碼嘞?

對於正數來講,咱們把它的絕對值轉換成的二進制數叫作正數的原碼,對於負數來講咱們把它的絕對值轉換成的二進制數,而後最高位補1,稱爲原碼。看看,仍是有區別的。

好比 :

00000000 00000000 00000000 00000101 是 5的 原碼。
10000000 00000000 00000000 00000101 是 -5的 原碼。

這裏有個點就是最高位是0表明正數,是1表明負數。

正數和負數在計算機中怎麼表示的

接下來就是在計算機中的表示:

對於正數:原碼,反碼和補碼都是同樣的,因此在計算機中怎麼說都同樣,反正就是自己轉換成二進制的結果,能夠說原碼,也能夠說補碼,由於都是同樣的

對於負數:原碼,反碼和補碼是不同的,在計算機中負數是以補碼的形式存在的

因此說,重點聚焦在負數上,看它的反碼和補碼是怎麼表示的

反碼

那反碼是啥嘞?

負數的反碼爲對該數的原碼除符號位外各位取反[每一位取反(除符號位)]。

這裏有個符號位,啥?還記得剛剛說的嗎?

最高位是0表明正數,是1表明負數。

也就是最左邊的那一位。

取反操做指:原爲1,得0;原爲0,得1。(1變0; 0變1)

好比:

正數00000000 00000000 00000000 00000101 的反碼仍是
00000000 00000000 00000000 00000101

負數10000000 00000000 00000000 00000101 的反碼則是
11111111 11111111 11111111 11111010

另外啊反碼是相互的,所以也可稱:
10000000 00000000 00000000 00000101 和 11111111 11111111 11111111 11111010互爲反碼。

不過這裏有個問題,那就是+0和-0,什麼意思呢?

原碼和反碼在表示數的時候的有點尷尬啊,好比表示零的時候,一樣都是0,可是原碼就有兩種表示法:

 [-0]原=10000000

 [+0]原=00000000
複製代碼

反碼也有兩種表示法:

 [+0]反=00000000

 [- 0]反=11111111
複製代碼

這就有點難受啊,不都是0嗎,因而乎,就出了補碼

補碼

那啥又是補碼嘞?

負數的補碼爲對該數的原碼除符號位外各位取反,而後在最後一位加1

好比:10000000 00000000 00000000 00000101 的反碼是:11111111 11111111 11111111 11111010

那麼,補碼爲:
11111111 11111111 11111111 11111010 + 1 = 11111111 11111111 11111111 11111011

這裏有兩點須要注意:
一、從補碼求原碼的方法跟原碼求補碼是同樣的 ,也能夠經過徹底逆運算來作,先減一,再取反。
二、補碼卻規定0沒有正負之分

第二個啥意思呢,也就是說對於0的表示,補碼只有一種[-0]補=00000000。感受這樣就正常多了。

總結一下

原碼錶示法規定:用符號位(最左邊)和數值表示帶符號數,正數的符號位用「0」表示,負數的符號位用「1」表示,數值部分用二進制形式表示。

反碼錶示法規定:正數的反碼與原碼相同,負數的反碼爲對該數的原碼除符號位外各位取反。

補碼錶示法規定:正數的補碼與原碼相同,負數的補碼爲對該數的原碼除符號位外各位取反,而後在最後一位加1.

正零和負零的補碼相同,[+0]補=[-0]補=0000 0000B

簡單說說

其實你看,這些基礎知識仔細研究起來,仍是有必定難度的,以爲亂巴巴的,怪不得上大學的時候聽不懂呢😂,並且這三個知識點貌似常常一塊兒運用,因此對於這三點基礎,仍是有必要花時間琢磨一番的。

好啦,就到這了,歡迎你們一塊兒討論!

感謝閱讀

你們好,我是ithuangqing,一路走來積累了很多的學習經驗和方法,並且收集了大量的精品學習資源,如今維護了一個公衆號【編碼以外】,寓意就是在編碼以外也要不停的學習,主要分享java技術相關的原創文章,如今主要在寫數據結構與算法,計算機基礎,線程和併發以及虛擬機這塊的原創,另外針對小白還在連載一套《小白的java自學課》,力求通俗易懂,由淺入深。同時我也是個工具控,常常分享一些高效率的黑科技工具及網站

對了,公衆號還分享了不少個人學習心得,能夠一塊兒探討探討!

關注公衆號,後臺回覆「慶哥」,2019最新java自學資源立馬送上!更多原創精彩盡在【編碼以外】

在這裏插入圖片描述
在這裏插入圖片描述

感謝各位大大的閱讀🥰

相關文章
相關標籤/搜索