解析機器中加減法對於二進位制補碼的運用(附python程式碼)
機器中的加減法並不像我們實際生活中一樣,帶有正負號,比較容易運算,機器中只有0和1,那就需要一種演算法來實現加減法運算。
首先,我們要明確目標是要進行帶符號的數字(signed)進行加減法運算。
由於沒有正負號,我們要採取一種措施來使某一位變為符號位,即最高位,如果是負數那麼表示1,正數即為0,不再贅述。
下面來表示幾個數字,如:(在此,用8位來表示一個數字,即1Byte)
1: 0000 0001
-1:1000 0001
0:0000 0000
每個數字有三種表示形式:(過餘碼不介紹)
1.原碼
2.反碼(正數反碼和原碼相同):原碼最高位符號位不變,其餘位取反
3.補碼(正數補碼和原碼相同):原碼最高位符號位不變,其餘位取反加一
由於原碼中最高位用來表示符號位,所以表示範圍為-127~+127,包含正0和負0
而補碼的表示範圍為-128~+127
這就導致了-128無法由補碼轉為原碼,-128的補碼錶示為:1000 0000
在計算中也可能產生溢位的情況,不過本文並未加以贅述。如127+127如果用補碼運算並非254,因為原碼錶示範圍有限,不過補碼的意義就是對256進行同模運算,318和62對256是同模的,所以補碼均為0011 1110,最高位溢位丟失。
計算機中加法實則是補碼的加法,減法也有多種方法。
如:45+22->
0010 1101
+ 0001 0110
= 0100 0011->和為67的補碼
如 54+(-73)->
0011 0110
+ 1110 1101
= 1001 1001 ->和為-103的補碼
減法也是同理:其實和加法相同,
(1)採用減法表即可:
-01
00-1
110
如果產生-1則相應Carry Flag置1即可
或者
(2)採用加上一個負數的形式,具體如:
1111 0000 - 0000 1111 = 1111 0000 + (-0000 1111),再求出相應補碼進行運算
(3)加上一個'最大值'
何為最大值呢?例如,我們在進行十進位制減法時,經常採取Borrow的方法,即借位,借位就是加上一個9
如 253-176,計算的方法就是
999-176 = 823
253+823 = 1076
1076+1-1000 = 77
而當被減數小於減數時,如:176-253,為了避免借位,我們首先要從999中減去減數,
999-253 = 746
176+746 = 922
922 - 999 ?我們已經意識到了,減去最大的數一定是個非正數,所以我們交換
-(999 - 922)= -77
而在二進位制中借位如何表示呢?
借用1111 1111一切問題迎刃而解,事實上,補碼的意義就是在這種運算中得出的結論。一切步驟與十進位制相似。
附上python中求補碼和加法的程式碼(python初學者),並沒有編寫補碼求原碼的過程,即需要減一求反碼:
#coding=gbk
#將對應數字轉換為二進位制
def orgin(num ):
if num >= 0:
dest_bin = ['0']
else:
dest_bin = ['1']
num = abs(num)
i = 64
while(i):
if( num/i ):
temp = ['1']
num -= i
else:
temp = ['0']
dest_bin = dest_bin + temp
i /= 2
return dest_bin
#轉換為補碼前要取反
def inverse( org_num ):
i = 1
while(i < len(org_num)):
if org_num[i] == '0':
org_num[i] = '1'
elif org_num[i] == '1':
org_num[i] = '0'
i += 1
return org_num
#進行補碼的加法
def add_bin( num1, num2):
len1 = len(num1)
sum_num = ['0']*len1
carry_flag = 0
while(len1 >= 0):
len1 -= 1
sum = int(num1[len1]) + int(num2[len1]) + carry_flag
if sum == 0:
pass
elif sum == 1:
sum_num[len1] = '1'
carry_flage = 0
elif sum == 2:
carry_flag = 1
sum_num[len1] = '0'
elif sum == 3:
carry_flag = 1
sum_num[len1] = '0'
return sum_num
#轉換相應的數字為補碼
def tran( num ):
print '%d:' % num
if num == -128:
return ['1']+['0']*7
elif(num >= 0):
return orgin(num )
else:
str_temp = orgin(num )
str_temp = inverse(str_temp)
str_temp = add_bin(str_temp, ['0']*7+['1'])
return str_temp
def display( num):
for i in num:
print i,
print
if __name__ == '__main__':
display(tran(1))
display(tran(-127))
display(tran(-128))
display(tran(-127))
display(tran(88))
display(tran(0))