天天看點

重學計算機組成原理(十)- "燙燙燙"亂碼的由來(上)1 了解二進制的“逢二進一”

重學計算機組成原理(十)- "燙燙燙"亂碼的由來(上)1 了解二進制的“逢二進一”

程式 = 算法 + 資料結構

對應到計算機的組成原理(硬體層面)

  • 算法 — 各種計算機指令
  • 資料結構 — 二進制資料

計算機用0/1組成的二進制,來表示所有資訊

  • 程式指令用到的機器碼,是使用二進制表示的
  • 存儲在記憶體裡面的字元串、整數、浮點數也都是用二進制表示的

萬物在計算機裡都是0和1,搞清楚各種資料在二進制層面是怎麼表示的,是我們的必修課。

在實際應用中最常遇到的問題,也就是文本字元串是怎麼表示成二進制的,特别是我們會遇到的亂碼究竟是怎麼回事兒

在開發的時候,所說的Unicode和UTF-8之間有什麼關系。

了解了這些,相信以後遇到任何亂碼問題,你都能手到擒來了。

1 了解二進制的“逢二進一”

二進制和我們平時用的十進制,并沒有本質差別,隻是平時是“逢十進一”,這裡變成了“逢二進一”

每一位,相比于十進制下的0~9這十個數字,我們隻能用0和1這兩個數字。

任何一個十進制的整數,都能通過二進制表示出來

把一個二進制數,對應到十進制,非常簡單,就是把從右到左的第N位,乘上一個2的N次方,然後加起來,就變成了一個十進制數

當然,既然二進制是一個面向程式員的“語言”,這個從右到左的位置,自然是從0開始的。

比如0011這個二進制數,對應的十進制表示,就是

0×2

3

+0×2

2

+1×2

1

= 3 =3=3

代表十進制的3

對應地,如果我們想要把一個十進制的數,轉化成二進制,使用短除法就可以了

也就是,把十進制數除以2的餘數,作為最右邊的一位。然後用商繼續除以2,把對應的餘數緊靠着剛才餘數的右側,這樣遞歸疊代,直到商為0就可以了。

比如,我們想把13這個十進制數,用短除法轉化成二進制,需要經曆以下幾個步驟:

重學計算機組成原理(十)- "燙燙燙"亂碼的由來(上)1 了解二進制的“逢二進一”

是以,對應的二進制數,就是1101

剛才我們舉的例子都是正數,對于負數來說,情況也是一樣的嗎?

我們可以把一個數最左側的一位,當成是對應的正負号,比如0為正數,1為負數,這樣來進行标記。

這樣,一個4位的二進制數, 0011就表示為+3。而1011最左側的第一位是1,是以它就表示-3。這個其實就是整數的原碼表示法

原碼表示法有一個很直覺的缺點就是,0可以用兩個不同的編碼來表示,1000代表0, 0000也代表0。習慣萬事一一對應的程式員看到這種情況,必然會被“逼死”。

于是,我們就有了另一種表示方法。我們仍然通過最左側第一位的0和1,來判斷這個數的正負。但是,我們不再把這一位當成單獨的符号位,在剩下幾位計算出的十進制前加上正負号,而是在計算整個二進制值的時候,在左側最高位前面加個負号。

比如,一個4位的二進制補碼數值1011,轉換成十進制,就是

−1×2

= − 5 =-5=−5

如果最高位是1,這個數必然是負數;最高位是0,必然是正數。并且,隻有0000表示0,1000在這樣的情況下表示-8。一個4位的二進制數,可以表示從-8到7這16個整數,不會白白浪費一位。

當然更重要的一點是,用補碼來表示負數,使得我們的整數相加變得很容易,不需要做任何特殊處理,隻是把它當成普通的二進制相加,就能得到正确的結果。

我們簡單一點,拿一個4位的整數來算一下,比如 -5 + 4 = -1,-5 + 6 = 1

我們各自把它們轉換成二進制來看一看。如果它們和無符号的二進制整數的加法用的是同樣的計算方式,這也就意味着它們是同樣的電路。

繼續閱讀