解析机器中加减法对于二进制补码的运用(附python代码)

来源:互联网 发布:ican3官方软件下载 编辑:程序博客网 时间:2024/05/18 02:49

机器中的加减法并不像我们实际生活中一样,带有正负号,比较容易运算,机器中只有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

0 0-1

1 10 

如果产生-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))

0 0
原创粉丝点击