补码的运算

来源:互联网 发布:淘宝电影在线 编辑:程序博客网 时间:2024/06/04 17:45

     我们知道补码的值可以用反码加1得到,我的上一篇介绍了一些反码的计算,反码的计算是为了将加法和减法都通过加法器实现(这里用到了同余概念,和钟表循环的原理类似,你想调到到一个时间即可以通过让指针倒退的方式,也可以通过让指针正向旋转得到。例如如果当前时间是6点, 我希望将时间设置成4点。那么可以向后拨2小时,或者向前拨十个小时。反码和补码计算的原理和这个差不多,只不过相应的值由'12"变成“127”和“128”。感兴趣的可以看看这篇博客:点击打开链接)。扯远了,言归正传,反码计算时会有个关于0的问题,通过反码计算1-1可以得到:

    

1 - 1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原= [0000 0001]反 + [1111 1110]反 = [1111 1111]反 =[1000 0000]原 = -0
    这样一来就有了两个问题:1.出现了-0这种形式,实际上0是不需要符号的  2. 0有两个编码[0000 0000]和[1000 0000](原码) 。补码的出现就是为了应对这个问题:   

1-1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原 = [0000 0001]补 + [1111 1111]补 = [0000 0000]补=[0000 0000]原

    这样0用[0000 0000]表示, 而以前出现问题的-0则不存在了.而且可以用[1000 0000]表示-128,即表示一个最低位。所以8位二进制原码和反码范围都是[-127,127],而补码则可以表示[-128,127]。

     关于补码运算,我起初的疑惑依然出现在最高位。补码的最高位计算时与反码不同是需要弃位,直接上例子: 

(-1) + (-127) = [1000 0001]原 + [1111 1111]原 = [1111 1111]补 + [1000 0001]补 = [1000 0000]补  

      符号位1+1后舍弃(这里要注意和进位的区别)


      简单说下补码溢出的问题,首先只有真正意义上的相加才可能溢出,比如:正+正,负+负,正-负,负-正; 至于正-正,正+负这些是不会溢出的。

      先举一个典型的溢出例子,以8位二进制为例:

127+1=[0111 1111 ]补 + [0000 0001]补=[1000 0000]补 

      符号位都变了,显然溢出了。,很多人会疑惑两个负数补码的符号位都是1,相加后不就为0了?两个负数相加成为正数了,显然不对。

      以8位补码为例,负数原码和补码数值部分之和始终等于128(看了文章开头关于同余概念的应该都知道为什么),所以说抛开符号位,原码的值越大补码的值也就越小。这样一来,如果两个原码相加的值超过了128,则补码值的相加必然小于128,不会向符号位进位;反之,原码的值越小,补码的值也就越大,这时则会向符号位进位。所以在未溢出的情况下,补码相加的值都会向符号位进位。这样符号位的1+1舍弃后,通过进位后发现符号位依然是1,依然是负数。

       简单的说,两个负数相加计算时只要不是溢出的情况下计算出的值必然会向符号位进位。假如没有进位呢?那说明溢出了。