計算機的運算方法




計算機的運算方法

無符號數

計算機中的數存放在寄存器中,通常將寄存器的位數稱為機器字長, 大家說的無符號數其實就是不區分正負號的數,換句話說,就是沒負數,全是正數,大家知道,計算機中的數是以0-1存儲的, 假如我們的寄存器16位, 無符號數表示的范圍就是0~65535 (2^64=65536), 有符號就是分正負數,總數65536就被分成兩半,一半正數,一般負數,范圍就是 -32768~32767

有符號數

有符號數,就是正負數同時存在, 人們固然能區分開整正負數,計算機怎么區分呢?

前面說了,計算機只認識01這樣的數,於是人們規定 0表示正數, 1表示負數, 於是這樣符號就被數字化了, 並且規定將其放在真實值前面, 於是有符號數就誕生了

真值和機器數

如上圖,按照計算機存數數據的特性將符號數字化, 數字化后的編碼方式得到的結果稱為機器數, 將帶有+-符號的數字稱為真值

既然現在將有符號數數字化后,新的問題來了,當這些機器數之間需要進行運算時, 符號位怎么辦? 符號位能否參加機器數之間的運算呢? 如果說,需要參加運算又需要哪些處理才能消除符號位對計算結果的影響呢? **這一連串問題就引出了符號位和數值位所構成的編碼: 原碼 , 補碼 , 反碼 , 移碼 **

其實在學習的過程中該一直問自己,自己在干什么??? 就比如現在,我在前面大概說了說計算機是如何表示數字的,於是認識了機器碼,機器碼之間需要進行運算於為了設計出使機器碼運算的方式,人們對機器碼進行不同的變形編碼,得到了,原碼 , 補碼, 反碼 , 移碼等, 下面看一下這幾種編碼的由來,以及他們對實現機器碼的可計算的貢獻

原碼

原碼是機器碼最簡單的一種變形,同樣的它的符號位0表示正數,1表示負數。 數值位就是真值的絕對值

人們為了書寫方便已經區分小數和整數,在符號位和數值位之間使用逗號分隔

整數的原碼

整數原碼

舉個例子:

x= +1110, 那么它的原碼就是 0,1110
x= -1110, 原碼=1,1110

小數的原碼

小數原碼

舉個例子

x= 0.1101 ,  那么它的原碼就是      0.1101
x= -0.1101,  原碼=1 - (-0.1101) = 1.1101

看上面的原碼計算方式,顯然機器碼很容易就轉成原碼,但是想想如果用原碼進行數值運算的話就會帶來很多麻煩,我們得先判斷兩個機器數絕對值的大小然后用大的減去小的,最終的符號再按照絕對值大的算, **而且我們需要設計兩套運算流程,一套給加法用,一套給減法用, 但是前輩們很智慧,因為人們找到了一種方式,找到了一個正數去替換原來減數位置的負數,類似像下面這樣,實現了在計算機中僅僅設計一套加法器就實現加減法的運算 **

5-3=2
5+(-3)=2

上述方法的實現就依賴於下面的補碼

補碼

補碼的概念和補數的概念很像, 比如現在時鍾六點了,我們想讓它指向三點,於是我們可以往回轉3(6-3=3)圈時針能回退到3點,也可以往前轉9圈(6+9=15),可以前進到三點, 對時鍾來說往順時針還是逆時針的過程不一樣,但是對我們來說結果是一樣的,都是三點了

這個過程就類似於,找到一個正數,讓這個正數代替負數去參加運算,使用加法運算器也能得到正確的結果

時鍾旋轉一圈12小時,在這12小時中是不被顯示且自動丟失的,也就是說 15-3=3 點, 於是我們可以說,其實對時鍾來說, -3 +9 的作用其實是一致的,結果都是三點, 在數學上我們將12稱為模 ,寫成mod 12 , 我們管9 稱為是 -3以12為模的補數

於是我們得知,只要我們確定了模,我們就能求出這個數對這個模的地位相同的補數,或者說當我們想將已知的負數轉換成可以替換他的正數的話,借助模就可以完成

如何利用模求補數呢?

  • 正數的補數是它本身
  • 負數可以用它的正補數等價替換
  • 負數的補數= 模+負數本身

如何進行求模示例:

-3    全等於 +7    (mod10)
+7 	  全等於 +7    (mod10)
-3 	  全等於 +97   (mod100)

-1011 全等於 +0101    (mod2^4)
2^4=1 0 0 0 0
-	  1 0 1 1
---------------
      0 1 0 1
   
+0101  全等於 +0101   (mod2^4)

小數的mod = 2
+0.1001 全等於 +0.1001  (mod2)

-0.1001 全等於 +1.0111  (mod2)
 1 0.0 0 0 0
-  0.1 0 0 1
--------------
   1.0 1 1 1


求補碼的公式

正補公式

求負數補數的示例

正補示例

其實大家可以看一下,對負數的公式來說,公式中的n就是負數的位數, -1101 一共四位, n=4, 但是取的是n+1位, 換句話說是用一個比原負數多兩位的數加上這個負數, 多出來一個符號位, 最后的結果中別忘了用 逗號分隔符號位和數值位, 當然這是為了方便我們自己看,讓人們一眼看去知道最開始的1是個符號位,后面的數才是 想求的補數結果

小數求補碼的公式

小數補碼公式

舉個例子: 求 -0.0110 的補碼

求小數的補碼示例

此外, +0 -0的補碼都是 0

從上面的討論我們知道,之所以想引入補碼是為了消除減法運算,即將一個負數轉換成它的正數補碼,但是根據補碼的定義,大家可以看到上面的兩個例子,在產生補碼的過程中又出現了減法運算,怎么辦呢?

於是我們這樣求補碼: 先求原碼, 然后變換這個原碼得到補碼, 怎么變換呢? 就是將除了 符號位的原碼其它為取反 之后再加1

舉個例子: 上面的就用 -1101 來說, 如下:

從原碼求補碼

於是看到這里我們徹底知道了,只為計算機設計一個加法器是完全ok的,下文會介紹如何運算

反碼

通過上面的運算我們知道下面的運算規則

原碼(符號位,數值位) => 除符號位外其他位取反  = 反碼
反碼+1 = 補碼
補碼-1 = 反碼

由此可知,其實這個反碼就是原碼和補碼雙方轉換時的中間狀態

小結

  • 原碼,反碼,補碼的最高位都是符號位, 符號位和數值位之間使用.或者逗號分隔(小數用點, 整數用逗號)
  • 真值為整數時, 原碼,反碼,補碼的表示形式是相同的
  • 雖然真值為負數時,原碼.反碼補碼各不相同,但是最高位的符號為都是1, 並且原碼求反+1=補碼 , 原碼每位求反=反碼

移碼

真值轉換成補碼后,由於符號位和數值位是一起進行編碼的,因此人們很難分清補碼之間的大小

就像下面這樣

十進制的21  對應二進制為+10101  補碼為 0,10101
十進制的-21  對應二進制為-10101  補碼為 1,01011
十進制的31  對應二進制為 +11111  補碼為 0,11111
十進制的-31  對應二進制為-11111  補碼為 1,00001

直觀上看他們的大小是 101011>010101 100001>011111 而實際上恰恰相反

於是我們這樣, 在每一個真值的基礎上加上一個2^n , 情況就發生了變化

+10101  加上2^5  得 110101
-10101  加上2^5  得 001011
+11111  加上2^5  得 111111
-11111  加上2^5  得 000001

這樣的話不需要借助補碼,六位代碼本身就能看到出真值的大小

更進一步,通過觀察可以發現,其實一個數的補碼和移碼之間就差一個符號位,換句話說,如果我們將補碼的符號位從0換為1,或者從1換成0得到的就是它的移碼, 在這基礎上比較大小得到的結果是准確的

此外正負零的移碼的一樣的

移位運算

計算機中的機器數的字長往往是固定的,當機器數左移n位或者是又移n位時,勢必會倒是另外一邊出現空位,那么在出現空位的位置到底是補充1還是填充0呢? 這取決於機器數是有符號還是無符號,其中有符號的機器數采取的位移稱為算數位移,無符號的唯一稱為邏輯位移

算數位移的移位規則

真值 碼制 補填代碼
正數 原碼,補碼,反碼 0
負數 原碼 0
負數 原碼 左移添0
負數 補碼 右移添1
負數 反碼 1

無論是正數還是負數,移位后的符號位都是不變的

舉幾個例子


		機器數        十進制
移位前 : 0,0011010      +26
左移1位: 0,0110100      +52
右移1位: 0,0001101      +13

左移一位,除符號位外原來的最高位被移走了,右邊空出的1位用0補全,但是高位丟失了其實得到的就是錯誤的結果,但是這個錯誤的結果恰好是原值的2倍,而且唯一運算速度還快,因此很多框架的底層都青睞使用這個位移運算的特性

每次右移時,最右邊的數就會丟失,精度收到影響

左移一位相當於乘以2,右移1位相當於除以2

邏輯位移的移位規則

邏輯左移,高位丟失,低位填0, 邏輯右移,低位丟失,高位補0

加法與減法運算

回到一開始話題,計算機的運算方法,前面通過補碼的介紹我們知道了只設計一套加法器其實是可行的,下面具體看一下是如何進行運算的

即 A-B = A + (-B)

補碼的加法公式

整數:  [A]補 + [B]補 = [A+B]補  (mod 2^n+1)
小數:  [A]補 + [B]補 = [A+B]補  (mod 2)

對於減法來說

整數:  [A-B]補 = [A]+[-B]補  (mod 2^n+1)
小數:  [A-B]補 = [A]+[-B]補  (mod 2)

最后看一個例子: 看看計算機如何將減法轉換成加法並攜帶符號位運行得出正確結果

假設機器8位(含一位符號位),若A=+15 B=+24, 讓我們求 [A-B]補 ,並還原真值

A=+15 = +0001111  (算上+號一共八位)	 	   
b=+24 = +0011000  (算上+號一共八位)

A和B都是整數,所以他們的補碼就是原碼本身:
[A]補 = 0,0001111
[B]補 = 0,0011000

[-B]原碼 = 1,0011000
[-B]反碼 = 1,1100111  ( 除符號位取反得到反碼:)
[-B]補   = 1,1101000   (由反碼+1得到)

[A-B]補 = [A]補 + [-B]補  
        = 0,0001111 + 1,1101000
        = 1,1110111
 
那么 A-B = 啥呢? 反着換回去
1,1110111 
1,1110110  (末位減1再取反)
1,0001001 = -0001001 = -9


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM