問一個基本的問題。
負數(shù)在計算機中如何表示涉茧?
舉例來說,+8在計算機中表示為二進制的1000疹娶,那么-8怎么表示呢伴栓?
很容易想到,可以將一個二進制位(bit)專門規(guī)定為符號位雨饺,它等于0時就表示正數(shù)钳垮,等于1時就表示負數(shù)。比如额港,在8位機中饺窿,規(guī)定每個字節(jié)的最高位為符號位。那么移斩,+8就是00001000肚医,而-8則是10001000。
但是向瓷,隨便找一本《計算機原理》肠套,都會告訴你,實際上猖任,計算機內(nèi)部采用2的補碼(Two's Complement)表示負數(shù)你稚。
什么是2的補碼?
它是一種數(shù)值的轉換方法朱躺,要分二步完成:
第一步刁赖,每一個二進制位都取相反值,0變成1长搀,1變成0宇弛。比如,00001000的相反值就是11110111源请。
第二步枪芒,將上一步得到的值加1轿钠。11110111就變成11111000。
所以病苗,00001000的2的補碼就是11111000。也就是說症汹,-8在計算機(8位機)中就是用11111000表示硫朦。
不知道你怎么看,反正我覺得很奇怪背镇,為什么要采用這么麻煩的方式表示負數(shù)咬展,更直覺的方式難道不好嗎?
昨天瞒斩,我在一本書里又看到了這個問題破婆,然后就花了一點時間到網(wǎng)上找資料,現(xiàn)在總算徹底搞明白了胸囱。
2的補碼的好處
首先祷舀,要明確一點。計算機內(nèi)部用什么方式表示負數(shù)烹笔,其實是無所謂的裳扯。只要能夠保持一一對應的關系,就可以用任意方式表示負數(shù)谤职。所以饰豺,既然可以任意選擇,那么理應選擇一種最方便的方式允蜈。
2的補碼就是最方便的方式冤吨。它的便利體現(xiàn)在,所有的加法運算可以使用同一種電路完成饶套。
還是以-8作為例子漩蟆。
假定有兩種表示方法。一種是直覺表示法凤跑,即10001000爆安;另一種是2的補碼表示法,即11111000仔引。請問哪一種表示法在加法運算中更方便扔仓?
隨便寫一個計算式,16 + (-8) = ?
16的二進制表示是 00010000咖耘,所以用直覺表示法翘簇,加法就要寫成:
00010000
+10001000
---------
10011000
可以看到儿倒,如果按照正常的加法規(guī)則版保,就會得到10011000的結果呜笑,轉成十進制就是-24。顯然彻犁,這是錯誤的答案叫胁。也就是說,在這種情況下汞幢,正常的加法規(guī)則不適用于正數(shù)與負數(shù)的加法驼鹅,因此必須制定兩套運算規(guī)則,一套用于正數(shù)加正數(shù)森篷,還有一套用于正數(shù)加負數(shù)输钩。從電路上說,就是必須為加法運算做兩種電路仲智。
現(xiàn)在买乃,再來看2的補碼表示法。
00010000
+11111000
---------
100001000
可以看到钓辆,按照正常的加法規(guī)則剪验,得到的結果是100001000。注意前联,這是一個9位的二進制數(shù)碉咆。我們已經(jīng)假定這是一臺8位機,因此最高的第9位是一個溢出位蛀恩,會被自動舍去疫铜。所以,結果就變成了00001000双谆,轉成十進制正好是8壳咕,也就是16 + (-8) 的正確答案。這說明了顽馋,2的補碼表示法可以將加法運算規(guī)則谓厘,擴展到整個整數(shù)集,從而用一套電路就可以實現(xiàn)全部整數(shù)的加法寸谜。
2的補碼的本質
在回答2的補碼為什么能正確實現(xiàn)加法運算之前竟稳,我們先看看它的本質,也就是那兩個步驟的轉換方法是怎么來的熊痴。
要將正數(shù)轉成對應的負數(shù)他爸,其實只要用0減去這個數(shù)就可以了。比如果善,-8其實就是0-8诊笤。
已知8的二進制是00001000,-8就可以用下面的式子求出:
00000000
-00001000
---------
因為00000000(被減數(shù))小于0000100(減數(shù))巾陕,所以不夠減讨跟。請回憶一下小學算術纪他,如果被減數(shù)的某一位小于減數(shù),我們怎么辦晾匠?很簡單茶袒,問上一位借1就可以了。
所以凉馆,0000000也問上一位借了1弹谁,也就是說,被減數(shù)其實是100000000句喜,算式也就改寫成:
100000000
-00001000
---------
11111000
進一步觀察沟于,可以發(fā)現(xiàn)100000000 = 11111111 + 1咳胃,所以上面的式子可以拆成兩個:
11111111
-00001000
---------
11110111
+00000001
---------
】跆11111000
2的補碼的兩個轉換步驟就是這么來的展懈。
為什么正數(shù)加法適用于2的補碼?
實際上供璧,我們要證明的是存崖,X-Y或X+(-Y)可以用X加上Y的2的補碼完成。
Y的2的補碼等于(11111111-Y)+1睡毒。所以来惧,X加上Y的2的補碼,就等于:
X + (11111111-Y) + 1
我們假定這個算式的結果等于Z演顾,即 Z = X + (11111111-Y) + 1
接下來供搀,分成兩種情況討論。
第一種情況钠至,如果X小于Y葛虐,那么Z是一個負數(shù)。這時棉钧,我們就對Z采用2的補碼的逆運算屿脐,求出它對應的正數(shù)絕對值,再在前面加上負號就行了宪卿。所以的诵,
Z = -[11111111-(Z-1)] = -[11111111-(X + (11111111-Y) + 1-1)] = X - Y
第二種情況,如果X大于Y佑钾,這意味著Z肯定大于11111111奢驯,但是我們規(guī)定了這是8位機,最高的第9位是溢出位次绘,必須被舍去瘪阁,這相當于減去100000000撒遣。所以,
Z = Z - 100000000 = X + (11111111-Y) + 1 - 100000000 = X - Y
這就證明了管跺,在正常的加法規(guī)則下义黎,可以利用2的補碼得到正數(shù)與負數(shù)相加的正確結果。換言之豁跑,計算機只要部署加法電路和補碼電路廉涕,就可以完成所有整數(shù)的加法。
文章轉載自:http://www.ruanyifeng.com/blog/2009/08/twos_complement.html