電腦科學裡的補數
眾所周知電腦可以說是由 0 個及 1 所組成,所以使用的是二進位的方式,而補數的意義在於電腦的二進位的世界中,會需要表示「正數」跟「負數」,補數算是其中一種方案。
兩種表示正負數的方案
- 符號-絕對值表示法
意思是最高位代表正負,剩下表示數值。
對人類來說最直覺,但是對電腦來說計算很麻煩。
例如 +5 (00000101) 加上 -5 (10000101),直覺上應該等於 0,但是單純丟進加法器會得到 10001010,其實不是 0 代表還要額外處理。
另外 -0 的時候會很奇怪,電腦中 0 理論上只有一種表示法,但是絕對值表示法時會變成這樣:
正零 = 00000000
負零 = 10000000
不是很對勁,所以第二種方式會好一些。
- 補數表示法
透過補數把「減法轉換成加法」。
實際方式可以分成一的補數跟二的補數,接下來會細談差異。
一的補數
定義是把所有二進位位元反轉,0 → 1,1 → 0。
以八位元表示做一個範圍:
+5 = 00000101
-5 = 一的補數 = 11111010
但還是會有 +0 跟 -0 的問題,同樣都是 0 卻有兩種表示方式。
以及運算時還考慮循環進位這件事情,所謂的循環進位是因為在一般的補數中,負數是「取反」來表示的,所以在做加法的時候,會有機會多產生一個超過最高位的進位,而在一的補數規則中,這個多出來的進位不能丟掉,而且要加回到最低位。
用實際例子來舉例:
+7 = 0111
+3 = 0011
所以 -3 一的補數是 1100
1 | 把兩個做加法: |
結果會發現變成了 10011,從 4 位元變成了 5 位元,前面多出來的那個 1 就是所謂的循環進位。
處理循環進位方法也很簡單,就是把最高位的 1 給加回到最低為就好了。
1 | 0011 |
結果的 0100 就是 4,這樣答案就是正確的。
二的補數
上面的提到過一的補數,二的補數就是在「一的補數」基礎上再 +1 ,可以當作取反 +1 就好。
一樣做一個 8 位元的範例:
+5 = 00000101
-5 = 11111011
(步驟就是 00000101 → 取反 11111010 → 加一 11111011)
這樣好處很多
變成不管是正是負只有一個 0 了(
00000000)加減法可統一處理,不用考慮上面提到的循環進位
一樣做一個跟上面相同的範例,我要 (+7) + (-3)
+7 = 0111
-3 = 1101(取反 0011 → 1100,加 1 → 1101)
1 | 0111 |
因為丟掉溢位的 1 → 0100 = 4,這樣就完全不需要再加回去。
補充為什麼我要研究補數的原因
有聽友人提到 1001 可以是 9,我想法是四個數字應該弄不出 9 才對,他的想法我猜是 1000 是 8 的話1001 就是 9,當下想想也有道理,但覺得怪怪的。
最奇怪的地方在於我覺得 1001 也是 -1,那這個我該怎麼區分 9 跟 -1 呢? 我的觀念整個亂掉了。
研究後我知道為什麼了,待我一一說明。
1001 是 9 的情境在於無號整數,也就是沒有符號的二進位,這個前提下每一個 bit 都是數值的一部分,所以 1001 是 9 成立。
但在有號數數裡面因為要表達「有正有負」這件事情,所以就要決定最高位這件事情。
在上面提到的符號-絕對值表示法套用到這個案例來說,1001 代表 -1 ,因為第一位代表符號的正負,剩下三位都是數值。
而二的補數 1001,運作就要取反再加 1 ,會是 -7,但又要注意一件事情,這是發生在 4 位元的情況下,因為最高位是 1 才會 -7,如果是 5 位元就會變成 01001,因為最高位是 0,所以取反再加 1 就會變成 +9。
所以正確的方式是要先確定有多少位元,然後再看要用什麼方式來解讀,才能正確得到數字。
不然其實 1001 可以是 9、-1、-7,不同的解讀方式下,數字都會不同。
結語
電腦要表示負數的方式有這三種,符號-絕對值表示法、一的補數、二的補數,符號-絕對值表示法太多缺點所以很少用,而一的補數相加有溢位的時候要用循環進位加回去,二的補數不用,單純自動就對了,不需要特別處理。
所以現代電腦也都捨棄一的補數(爬文看起來是這樣),改用二的補數。
原理簡單來說就是這樣,目前我自己覺得對補數比較有概念了。
望周知,謝謝觀看。
