計算機補碼運算背後的數學原理是什麼?

時間 2021-05-29 22:43:36

1樓:SleepyBag

想象乙個時鐘,指標指向的數字是計算機儲存的數字。給這個數字做加法,就是把指標順時針撥動;做減法,就是把指標逆時針撥:

普通表盤

當然,由於表盤大小是有限的(圖中的大小是 8),如果撥得太遠,指標可能會從兩個方向超過 0,也就是發生上溢或者下溢。上溢時,你得到的數字是期望結果 - 8;下溢時,你得到的數字是期望結果 + 8.說簡潔一點,就是所有的運算結果都會模 8.

時鐘上只有 0 和大於 0 的數字,不能表示負數,這當然很不方便。所以我們保持 0 的位置不動,把 0 左邊的一部分數字認為是負數。然後我們還是可以通過順逆時針的撥動來實現加減法:

加入負數的表盤——只需要改一下刻度

可以看到,這個時鐘本身的工作方式不需要進行任何改變,就可以產生正確的結果。加法還是把指標順時針撥動,減法還是把指標逆時針撥動。而我們使用原先的運算邏輯就可以對新的數字產生正確的運算結果,這說明現在的表盤刻度與原先的刻度具有等價性:

也就是 -1 和 7 是等價的,-2 和 6 是等價的,以此類推。

這個現象在概念上叫同餘:因為表盤上所有運算最終都是要模 8 的(不然會被截斷),所以模 8 結果相同的數字在這個運算體系中是等價的。比如說 -1 與 7,模 8 都等於 7,所以兩者在運算過程中可以相互替代。

正因為如此,我們雖然把表盤上的數字採取了不一樣的解釋,但是由於新的解釋與原先的數字是模 8 同餘的,所以運算邏輯不需要進行改變。

現在,我們把表盤上的數字按照 0~7 寫成二進位制,再來看看:

內圈是有符號數字,外圈是數字的補碼

——這就是補碼。

那這麼來定義表盤刻度有什麼好處呢?或者說,使用補碼來定義負數的二進位制表示有什麼好處呢?

我們可以發現,我們給表盤中加入負數之後,鐘錶的運算邏輯沒有發生變化,唯一發生變化的是它的刻度。但是刻度這個東西是是給人來讀的,時鐘自己不知道自己現在是幾。

也就是說,有符號數(也就是 -4~3)與無符號數(也就是 0~7)的運算是一樣的,處理器不需要知道自己在處理有符號數還是無符號數,直接當做有符號數來處理即可。有符號數與無符號數之間的區別只是上層對數字的解釋,也就是我們到底是把 111 解釋為 7 還是 -1。

2樓:夢逸清塵

blog.csdn.net/WUDIxi/ar

ticle/details/105854112

人類習慣於用十進位制數進行運算,而計算機的每個位卻只有0和1兩種狀態,換句話說,計算機採用的進製是二進位制。

因此,我們面臨的第乙個問題就是計算機如何用二進位制來表示十進位制數字。

對於正數而言,可以直接用該數的二進位制形式來表示,例如,十進位制數2,其在計算機中的表示為(假設計算機的字長為8):

0000

0010

但是這樣做會帶來乙個問題,如何表示負數呢?為此,我們採用犧牲最高位的辦法,將其視作符號位,並用1表示負,0表示正(這樣做是可以接受的,因為雖然正數的表示範圍由之前的 [1, 255] 縮小到了現在的 [1, 127], 但是我們卻因此收穫了 [-127, -1] 的負數表示範圍;另一方面,引入符號位後,[1, 127] 內的正數的表示方式並沒有發生改變,換句話說,引入符號位前後,正數的表示方法是相洽的)。

例如,十進位制數-2,其二進位制表示現在變為:

1000 0010

這裡,我們便可以引入原碼的概念

原碼:原碼是指乙個二進位制數左邊加上符號位後所得到的碼,且當二進位制數大於0時,符號位為0;二進位制數小於0時,符號位為1。[1]

原碼很直觀,人類可以直接理解原碼。

但是原碼是不是完美的呢?很顯然,它是有缺陷的。

1)十進位制數0的原碼並不唯一,以下兩個都是0的原碼。

0000 0000

1000 0000

2)當進行有負數參與的運算時,原碼將暴露更大的缺陷,例如:-3+2:

1000 0011 #-3的原碼

+ 0000 0010 #2的原碼1000 0101 #-5的原碼

我們得到了-5,這顯然是個錯誤結果。

為此,我們需要介紹補碼這個新概念

補碼:正數和0的補碼就是該數字本身。負數的補碼則是將其對應正數按位取反再加1。[2]

例如,2的補碼即為:

0000 0010

-2的補碼為:

# 1. 將-2對應的正數2,按位取反得到:1111 1101

# 2. 1111 1101再加1即得到: 1111 1110,為-2的補碼

1111 1110

0的補碼只有乙個,為:

0000 0000

現在我們再來驗證一下補碼在進行加減運算時是否能得到正確結果,同樣是-3+2:

1111 1101 #-3的補碼

+ 0000 0010 #2的補碼1111 1111 #-1的補碼

可以看到,我們得到了正確答案。

事實上,補碼是計算機真正用來表示二進位制數的方式,驗證如下:

#include

using

std::

cout

;int

main

()我們知道數軸上的點與實數是一一對應的,先來看看我們最熟悉的十進位制數在數軸上的排列:

因此,對於數軸上的任意乙個數,其加上乙個正數,則表示其在數軸正方向上移動了一段距離;而減去乙個正數(等價於加上乙個負數),則表示其在數軸負方向移動了一段距離。這是確保我們在進行數的加減時得到正確結果的關鍵。

當我們引入了原碼,那麼數在數軸上又是如何排列的呢,可以驗證,它們的排列變成了下面這個樣子:

注意:0在這裡是乙個關鍵的分界線,對於負數而言,它們的「0」 是1000 0000;而對於正數而言,它們的「0」是0000 0000。

仔細觀察,我們會發現,這個數軸有兩個正方向(這裡我們把加上乙個正數,數字移動的方向定為正方向):當乙個負數加上乙個正數,數字往左邊移動,例如:-3+2,結果變成了-5;當乙個正數加上乙個正數,數字往右邊移動,例如3+2,我們得到5.

這就解釋了為什麼原碼在加減運算中會出錯的原因。

回到補碼,如前所述,乙個負數的補碼就是是將其對應正數按位取反再加1。但是這裡對於補碼的敘述並不直觀,甚至會讓人有點摸不著頭腦,為了更好地理解補碼究竟在做什麼,我們不妨將-2的補碼與其對應正數2的補碼相加,看看會得到什麼結果:

0000 0010 # 2的補碼

+ 1111 1110 #-2的補碼1 0000 0000

這樣,我們就發現了對乙個負數求補碼的本質:

負數A_補 = 模-絕對值(A)

模的值,等於 ,n為字長。例如,對-2求補碼:

-2補= 2^8 - 0000 0010#2的補碼

= 10000 0000 - 0000 0010

= (1111 1111 - 0000 0010) + 1

#即等於2先按位取反,再加1

因此,引入補碼後,數字在數軸上的排列變成了下面這個樣子:

這裡,不僅0只有乙個表示,而且數軸也只有唯一乙個正方向,從而保證了運算的正確性。而這個保證,仔細思考一下就會發現,正是利用了負數A的絕對值與其補碼之和等於模,從而將負數部分的數軸方向調轉。

注:考慮到計算機存在「溢位」的現象,因此更為正確的表示應該採用數環,而不是數軸,不過,理解用的話,數軸足夠了。

1. 為什麼要引入補碼?

答: 1. 0的原碼有兩個,處理起來不方便;2. 原碼不能直接相加減;

2. 引入補碼的好處?

答:1. 0的補碼只有乙個;2. 變減法為加法,即減法和加法共用一套底層電路;3. 補碼之間可以直接相加減,最高位可以接受進製。

[1] https://zh.wikipedia.org/wiki/原碼

[2] https://zh.wikipedia.org/wiki/補碼

3樓:豬鼻蛇

乙個模運算你們能扯這麼多有的沒的還真是厲害……將補碼視為取反加一的解釋:

顯然有:

寫補碼時可以視最高位為-2^(n-1)其餘位為2^i進製直接寫的解釋:

4樓:

補碼和原本的數在模2^n(n是位數)下同餘,對負數就是加上2^n,這樣把通常的加法轉換成了非負數在模2^n下的加法,便於計算機運算

5樓:涵哥哥

補碼是為了運算時用正數來代替負數

8位帶符合整數(補碼範圍-128到127) 遇到負數找到對應的正數例如下面遇到了負數-1,需要對其進行處理

127+ (-1

=127-1

=【127+(128-1)】mod 128 ----這裡計算出-1的補碼為127也就是減一可以用加127來代替

=126

-1=1000 0001【原碼】=1111 1111【補碼】其去掉符號位是127的原碼

6樓:馮有洪

如果我們不用二進位制度而用10 進製去理解原碼反碼補碼, 乙個長度為3個數字可以表示0到999 範圍的數(1000 個數)。對於A-B(A>=B) 我們先不要理負數, A-B=A+(1000-B)-1000 因為A>=B, 所以 A+(1000-B) >1000因為這是乙個3 位數 >3 位的千位自動消失, 所以A-B=A+(1000-BA-B = A+(999-B+1)

現在引入負數的概念. 3 位數 0-499 表示0-499,, 500到999 就是表示 -500 到-1A-B= A+(-B) =A+(1000-B)-1000 因為3位數儘管是表示了負數但是還是用正數來表示負數所以A-B+1000還是會變成4位數還是自動消失1000 ,A-B=A+(1000-B) =A+(999-B+1)

所謂的反碼其實就是999減個三位數, 使每位加起來都是9。然後再+1 就是讓他爆位自動不見了1000。

而2 進製的反碼就是1111 1111 減去它, 而補碼就成了 1 0000 0000 減它

7樓:亂馬

要特別注意的是,所謂補碼符號位直接參與運算自動得到正確結果是有前提條件的,這個條件就是不溢位

溢位的定義有三種,最好理解的是:兩個符號相同的補碼數相加,如果和的符號與加數的符號相反,或兩個符號相反的補碼數相減,差的符號與減數的符號相同,都屬於運算結果溢位。

溢位了怎麼辦?溢位後代數結果已經不可能正確了,為了合理解釋加法電路的結果,我們定義這個結果的數學含義是「代數結果在定義區間『-128--127』內的補數」。

計算機內部 128是怎麼運算的?

川平馬一 128考慮為無符號整型資料是可以用8位二進位制表示的。在帶符號的整型資料裡,他的最高位只是符號位。剩下7位才是資料位,所以128無法使用8位二進位制數表達,存在溢位。 32位處理器,字長是32位,可以單指令計算32位和32位的加減法。如果遇到溢位,暫存器會有溢位標誌位被設定,此處可以寫程式...

國外的計算機專業 是如何教《計算機組成原理》這門課的?

c rt 新加坡國立大學的話大部分人是大三上,上的是cg3207 computer architecture。感覺教授的講義也是到處搬運的。然後剛開始就講一些相關的state of art然後正課具體的syllable我記不太全就不寫了,主要是四次project,從寫乙個加法器到寫乙個簡單的cpu再...

計算機判斷溢位的原理?

Sinaean Dean 你眼中的八位暫存器實際可以進行9位運算。第九位連在溢位標誌位上,你進行的運算不涉及第九位的時候第九位就是零,涉及到第九位的時候就是一,此時就溢位了。 北極 計算機中說的溢位 OF 一般是指補碼模式的加減運算的條件下。補碼模式有這麼幾個計算 轉化規則 X X Y Y X X ...