论补数和补码的关系

来源:互联网 发布:apache运行python 编辑:程序博客网 时间:2024/05/29 18:20

我们都知道,补数 引申到 计算机中 就是 补码的概念, 可是 为什么呢? 我们先来 看看 各自的 定义……

补数:

在日常生活中,常常会遇到补数的概念。例如,时钟指示为6点,欲使它指示3点,既可按顺时针方向将分针转9圈,又可按逆时针方向将分针转3圈,结果是一致的。假设顺时针方向转为正,逆时针方向转为负,则有:

                                                                                   6                6

                                                                                  -3               +9       

                                                                                  3                 15

        由于时钟的时针转一圈能指示12个小时,这“12”在时钟里是不被显示而自动丢失的,即15-12=3,故15点和3点均显示3点。这样-3和+9对时钟而言其作用是一致的。在数学上称12为模,写作 mod 12 ,而称 +9 是 -3 以 12 为模 的补数,记作:

                                                                                -3    +9        (mod 12)

或者说,对模12而言, -3 和 +9  是互为 补数的。同理有:

-4  +8 (mod 12)                       

-5  +7 (mod 12)   为什么叫补数呢?我觉得是因为 | A | + | B | = M ,这样看起来 A 和  B 互补--和数学中两个角互补类似)

即对模 12 而言, +8 和 +7 分别是 -4 和 -5 的补数。可见,只要确定了“模”,就可找到一个与负数等价的正数(该正数即为负数的补数)来代替此负数,这样就可把减法运算用加法实现。例如:

        设 A =9 , B =5 , 求 A - B (mod  12)

         解,A  -  B  =  9  -  5  =  4     (做减法)

        对模 12 而言,-5 可以用其 补数 +7 代替, 即

                             -5    +7       (mod 12)

        所以             A  -  B  =  9  +  7  =  16             (做加法)

        对模12而言,12会自动丢失,所以 16 等价于 4, 即 4   16 (mod  12) 。  #  联想 时钟, 就知道 16 和 4 指的位置是一样的,即作用相同。

       进一步分析发现, 3点、15点、27点……在时钟上看见的都是3点, 即  

                            3    15 27     (mod  12)

       也即             3    3 + 12    3 + 24 3   (mod  12)

       这说明,正数相对于“模”的补数就是正数本身。(例如在时钟上,15,27等始终指的都是3点,模12会自动丢失;一个数的补数等于这个数+模,再对模取余;所以补数 一定不大于模;而负数,在时钟上,表示逆时针旋转将分针旋转 | A | 圈,但由于时钟本身是顺时针旋转的,且 顺时针 旋转 M - | A | 圈,也能指向和逆时针旋转 | A | 圈一样的位置,所以 负数 可以 用其补数 来代替,这样就都是 顺时针旋转,即 运算中 就是 加法)

       #  在时钟中,补数 只有正数的概念,即便 是 负数,也应当转为 正数的补数形式, 不然 不具有 实际意义。

        上述,补数的概念 可以用到 任意 的 “模” 上,如:

         -3    +7   (mod 10)

        +7   +7    ( mod  10)

         -3   +97    ( mod  10^2)

        +97    +97    ( mod  10^2)

        -1011    +0101    ( mod  2^4)

        +0101  +0101    ( mod  2^4)

         -0.1001    +1.0111    ( mod  2)

        +0.1001   +0.1001    ( mod  2)            

由此可见:

1、一个负数可以用它的正补数来代替,而这个正补数可以用模加上负数本身求得;

2、一个正数和一个负数互为补数时,它们绝对值之和即为模数;

3、正数的补数还是该正数本身。

将补数的概念,引申到计算机中,就出现了补码这种机器码。  我们来看看补码的定义:  (以下,均来自唐朔飞的计组原理)

          

                

                          


#可以看到,在上述计算机定义里,补数的模长定为  2^(n+1) ,但是在计算机一个字节为8位,为表示有符号数(拿出一位表示符号),那么n=7就够了。(这里不考虑双符号位的补码)

        同时:  M = 2^8 = 1 0000 0000  =  1111 1111 + 0000 0001  ; 对于 求 -1的补数(补码),也就变为 1111 1111  -  0000  0001 + 0000 0001 = 1111 1111

        所以,求补码的公式也就出来了,全部取反后 +1;但考虑到 符号位的概念, 上式 变为  111 1111 - 000 0001 = 111 1111 ,加上符号为 1111 1111;公式就成了 负数的补码 是  “除 符号位以外,其余各位按位取反后 ,加1” .

        但是,最前面的 1 就是 负数 的补数(补码)的第一位啊,为什么,我们可以 规定 它的第一位为 1 代表负数。 因为,我们规定了一个8位二进制的 正数的符号位(第一位)为0 ,这样,不管 正数 是多少,其对应的负数, 最开始的 第一位 一定 是 1 , 你信,你可以 自己 举任何例子。  这样,不管是 有符号位,还是没有符号位, 其 求出 的 负数的补数 (补码) 都是正确的。 况且,一个数本来是负数,你用补数代替了,岂不成正数了,为了让补码(补数)在计算机中能被还原 为 负数,得让计算机 识别 这个补数 是 负数啊;计算机 就是 根据 首位 是 1 还是 0 ,来看 这个 补数(补码)是否为 负数的 ,然后 再 还原补数为 真正的 负数 和 正数 , 所以 符号位 必须得有。

我们再来看看 计算机中 ,如何用 补码 来运算?
1、用补码来表示负数就可以将加减法统一成加法来运算,简化了运算的复杂程度。  减法变为 被减数 +  减数相反数的补码。
例如:    8 -  (-8)   ==  8 +  8(-8补码的相反数的补码); 
                0000 1000  +  0000 1000 (-8的补码1111 1000的相反数补码是 0000 1000 ) =  0001  0000   这也就是 10进制 的 16
我们一般求一个数相反数的 补码思路是:补码-->原码 -->相反数原码  -->相反数补码
但实际上,可以 直接  套 公式 : (11111111 - 一个数的补码)+00000001=它相反数的补码 ; 假设 这个数 是 -8;代入公式有:
                 (11111111 - 1111 1000)+00000001  =  0000 0111 + 0000 0001 =  0000 1000  即它相反数(8)的补码。     
#这公式 也说明了,为什么,一个负数的补码是 其反码+1 , 1111 1111 - 一个数的补码 就是  按位取反,+ 0000 0001 就是加1。
# 上式 总结为:  "一个数 补码的补码  就是 其相反数的 补码" (无论这个数是 正数 还是 负数)
# 再有就是, -8 补码是 1111 1000 再求 补 后 为 8的 补码, 我们惊奇的 发现,8的补码就是 8的原码,所以正数 原 ,反,补一致。
#  当然,这里,我这里 ,可以说是 强行解释, 但也 不无 道理。 
2、采用补码进行运算有两个好处,一个就是刚才所说的统一加减法;二个就是可以让符号位作为数值直接参加运算,而最后仍然可以得到正确的结果符号,符号位无需再单独处理。
例如:  8 - 3  =  5  这个式子, 我们用 补码 来运算 一下 
0000 1000  + (-3)补  =   0000  1000  +  1111  1101  =  0000  0101   而这个 同样是 补码表示法, 但符号为0(正数原反补一致),所以一看 就是 5  ; 所以  式子 是正确的。
再看     8  -  9   =  -1  这个式子,被减数  和  减数 分别转为 补码后如下:
0000 1000  + (-9)补   =   0000  1000   +  1111  0111   =   1111  1111   ,而 这个 结果 不就是 -1  的 补码,同样正确,所以 确实如上述 补码优点 一样。 

3、再来看一个有趣的现象:

      8 的 补码是  0000 1000 ; 其相反数的补码是 1111 1000 ;而这个是怎么来的呢,就是0000 1000 全部取反为 1111 0111 然后 +1 ,得到 1111 1000;

      而这 与 上述 1 是一致的。那么,给定一个 负数,我们求它的补码 , 就有两种方法:第一种是 该负数相反数(即正数)原码全部取反后+1;第二种是负数原码 除符号位 以外,全部取反后+1  。

4、如果你还是对  补数为什么能引进计算机中,成为 补码 不明白,我再讲下自己的理解。

      补数 最大的特点是  补数之间做运算时,减法同样可改为 加法,考虑到 模的周期性和不显现性,使得 减法修改后的加法 运算 得出的 结果 也是正确的。

      就如 最开始所说的, 9 -5  (mod  12) 这个式子, 改为加法后是  9 + (12 - 5) =  9 + 7 = 16 , 由于 模12的不显现性 ,所以 16最终 -  12  得到 4 ,同样得到正确的结果;再来  8 - 9  (mod  2^n)这个式子,改为加法后 8 + 2^n - 9  =  2^n -1 ,计算机中n=8,2^8-1 就是 1111 1111,这就是-1的补码啊,从中,可以发现,用补码进行运算是完全正确的,没有问题的。计算机中的补码同样是 补数(只不过,计算机中模 为 2^(n+1)次方罢了,且均用二进制表示而已),所以 必然 也满足这个性质/规律, 所以 计算机中 补码  代替 原码 进行运算 也是正确的。  那么,你可能又要问了,要是两个数的和 大于 模 ,怎么办?  在 模的周期性和不显性下,进位岂不是 丢失掉了 。 这个,不需要我们考虑, 因为 进位 完全 可以 存放在  高位  字节 里,  丝毫 不影响  补码 的运算。


好了,不能再想这个问题了,不然 我又要花很多时间了,以上 纯属 个人观点,欢迎大家参考指正。

1 0
原创粉丝点击