數(shù)據(jù)表示基礎:計算機補碼運算原理
首先我們來看為什么要使用補碼運算法:
因為人腦可以知道第一位是符號位, 在計算的時候我們會根據(jù)符號位, 選擇對真值區(qū)域的加減. (真值的概念在本文最開頭). 但是對于計算機, 加減乘數(shù)已經(jīng)是最基礎的運算, 要設計的盡量簡單. 計算機辨別"符號位"顯然會讓計算機的基礎電路設計變得十分復雜! 于是人們想出了將符號位也參與運算的方法. 我們知道, 根據(jù)運算法則減去一個正數(shù)等于加上一個負數(shù), 即: 1-1 = 1 + (-1) = 0 , 所以機器可以只有加法而沒有減法, 這樣計算機運算的設計就更簡單了.
于是人們開始探索 將符號位參與運算, 并且只保留加法的方法. 首先來看原碼: 計算十進制的表達式: 1-1=0
1 - 1 = 1 + (-1) = [00000001]原 + [10000001]原 = [10000010]原 = -2 。如果用原碼表示, 讓符號位也參與計算, 顯然對于減法來說, 結(jié)果是不正確的.這也就是為何計算機內(nèi)部不使用原碼表示一個數(shù). 為了解決原碼做減法的問題, 出現(xiàn)了反碼: 計算十進制的表達式: 1-1=0 表達式1 - 1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原= [0000 0001]反 + [1111 1110]反 = [1111 1111]反 = [1000 0000]原 = -0
發(fā)現(xiàn)用反碼計算減法, 結(jié)果的真值部分是正確的. 而唯一的問題其實就出現(xiàn)在"0"這個特殊的數(shù)值上. 雖然人們理解上+0和-0是一樣的, 但是0帶符號是沒有任何意義的. 而且會有[0000 0000]原和[1000 0000]原兩個編碼表示0. 于是補碼的出現(xiàn), 解決了0的符號以及兩個編碼的問題: 表達式1-1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原 = [0000 0001]補 + [1111 1111]補 = [0000 0000]補=[0000 0000]原 。這樣0用[0000 0000]表示, 而以前出現(xiàn)問題的-0則不存在了.而且可以用[1000 0000]表示-128:
接下來我們來看補碼運算原理:
在計算機里,如果我們要計算5-3的值,我們既可以用5減去3,也可以用5加上13。這是為什么呢?
這就像我們的鐘表,它從1點走到12點之后,又回到了1點。我們的計算機也是,從0走到15之后,再往下走就又回到了0,就像我們轉(zhuǎn)了一個圈一樣。我們從5這個位置往回退3個格,就完成了5-3這個計算。我們也可以從5這個位置往前走,一直走到15,這時我們走了10個格,然后我們繼續(xù)往前走,走到0,然后到1,然后就走到了2。這樣,我們往前走了13個格之后,也到了2這個位置。
所以說,在我們這個計算機中,減3和加13是一樣的。而3+13=16,我們說在模16的系統(tǒng)下,3和13是互補的。
這樣,我們計算5-3就可以換成5+13。3的二進制表示為0011,5的二進制表示為0101。這樣,0101-0011就可以表示為0101+(-0011)。
我們在計算機中都是把負數(shù)用其補碼表示,-0011的補碼就是10000-0011(即16-3,也就是13)。10000-0011=1+1111-0011=1+(1111-0011)=1+1100=1101。
我們總說補碼是“按位取反再加一”,看了上面這個式子相信大家就會明白了,其實就是把10000-0011換成了1111-0011再加1的形式。然后,0101-0011就換成了0101+1101,它們計算出來的結(jié)果為10010。由于我們的計算機只有四個bit,所以結(jié)果為0010。即,在模16的計算機中,5-3=5+13=2。