(二)計算機如何保存字符和數字,並完成計算

1、保存字符

計算機在創建之初,只能顯示英文字母和特殊字符,後來慢慢纔有了其他語言。但是打開網頁或者編輯器卻可能出現亂碼。我們知道計算機只能保存0和1,那麼如何把字符保存成二進制,以及如何把二進制解碼成對應的字符就是先驅們所做的事情了。

我們學語言首先都會有一個字典,裏面保存了所有相關的字符,我們把字符的集合叫做字符集,例如 unicode字符集。而把字符集中的每個字符保存爲二進制,及如何把一連串的二進制解碼成對應的字符叫做字符編碼,例如 utf-8編碼。

而我們打開編輯器或者網頁出現亂碼,就是因爲保存字符用的字符編碼與把保存好的二進制進行解碼使用的字符編碼不一致導致的。

2、保存數字

整數在計算機中可以使用原碼,反碼或者補碼來保存。源碼保存整數很簡單,例如以四個字節來保存整數,5 對應原碼爲 00000000 00000000 00000000 00000101, -5對應的源碼則爲 10000000 00000000 00000000 00000101(最高位爲1)

反碼和補碼是針對原碼而言,它的規則如下:

  • 正數的反碼,補碼都與源碼一致,這是規則。
  • 負數的反碼,在源碼的基礎上,符號位不變,其它位取反
  • 負數的補碼,在反碼的基礎上,有效位+1

較爲複雜的是浮點數的保存,例如32位單精度浮點數保存格式如下:

該浮點數最終的值則爲:

其中e能夠表示的整數空間,就是 0~255。我們在這裏用 1~254 映射到 -126~127 這 254 個有正有負的數上。因爲我們的浮點數,不僅僅想要表示很大的數,還希望能夠表示很小的數,所以指數位也會有負數。而0和255則有特殊用處,如下:

0.1-0.9,計算機只能精準的表示0.5,即2的-1次方。由此可以得知計算機能精確表示的小數只能是 2的-n次方。所以0.3,0.4這些無法精確表示的小數,計算機只能通過近似值來表示,近似到直到把有效位數填滿。例如二進制的小數 0.1001 表示爲十進制則爲 2的-1次方 加上 2的-4次方。若要用二進制表示十進制的0.1,則用上面的方法一直往下累加,知道有效位數用完,但最終還是近似值。經典的例子:0.3+0.6 = 0.89999999...

3、從電路層面如何實現基礎邏輯

基礎邏輯即與門,或門,非門,異或門。我們假設每一個開關對應一個bit,開關閉合表示1,開關斷開表示0。則把兩個開關串聯表示與門,把兩個開關並聯則表示或門異或門則需要實現一個打開一個閉合時才能通電的電路,非門則可以通過通電後線圈產生的磁場控制開關來實現,如下圖

實現了基礎邏輯後,我們接着實現加法運算。A和B兩個bit相加,會產生一個進位U,一個當前位 S 的結果。U可以通過與操作得到,S可以通過異或操作得到。可以發現一個異或門+一個與門可以完成兩個bit的加法運算,我們稱作半加器,如下圖

若兩個數都擁有多位bit,相加時低位產生的進位數據會參與高位之間的求和,此時則需要接收低位傳過來的進位數據。我們可以用兩個半加器+一個或門實現。第一個半加器還是計算當前位的加法,產生一個進位U,一個當前位 S 的結果。第二個半加器則把當前位結果 S 和低位傳過來的進位 U0 相加得到一個進位 U1,一個當前位 S1 的結果(最終的當前位結果)。最後把兩個半加器產生進位進行或操作,得到最終的進位結果 U2。我們稱這位全加器,如下圖

把全加器組合串起來就可以得到加法器,對多位bit的數據進行加法運算。通過補碼運算,可以把減法運算變成加法運算;而乘法可以用加法來做,除法可以轉變成減法。這樣一來,加、減、乘、除四種運算“九九歸一”了。這對簡化CPU的設計非常有意義,CPU裏面只要有一個加法器就可以做算術運算了。通過加法器我們就可以得到算術邏輯單元(ALU)

4、如何完成計算

  • 正數+正數正常求解即可
  • 負數+負數正常求解後最高位強行製爲1即可
  • 正數+負數求解過程如下,先計算 正數補碼+負數補碼 得到結果A(超出最高位溢出的部分被忽略),此時的結果A是補碼,把A還原成原碼即爲最終的結果。
  • 兩個浮點數相加,先把指數位變成一樣,再把有效位的數相加。指數位變成一樣,意味着有效位需要進行移動,且只可能向右移動,否則左側數據丟失了。這樣一來,指數位小的數據在進行相加時就可能丟失精度。例如 20000000.0f + 1.0f = 20000000.0f。
  • 例如mysql中的decimal類型的數據,保存的不是近似值,而是採用準確保存方法,若要精確的數據則可以使用該類型。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章