1. 程式人生 > >解析機器中加減法對於二進位制補碼的運用(附python程式碼)

解析機器中加減法對於二進位制補碼的運用(附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))