程式 = 算法 + 資料結構
對應到計算機的組成原理(硬體層面)
- 算法 — 各種計算機指令
- 資料結構 — 二進制資料
計算機用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這個十進制數,用短除法轉化成二進制,需要經曆以下幾個步驟:
是以,對應的二進制數,就是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
我們各自把它們轉換成二進制來看一看。如果它們和無符号的二進制整數的加法用的是同樣的計算方式,這也就意味着它們是同樣的電路。