C语言学习之补码的深刻理解

来源:互联网 发布:谷越网络 编辑:程序博客网 时间:2024/04/29 14:28


    学到C语言的本质之补码时(http://learn.akae.cn/media/ch14s03.html)。发现不是很理解,特别是这段描述。

如果8个bit采用2'sComplement表示法,

负数的取值范围是从10000000到11111111(-128~-1),

正数是从00000000到01111111(0~127)。

      于是搜索了不少资料,总算理清了这一点。

首先,原码,反码,补码是一个真值用二进制表示的的不同方式。将一个真值表示成二进制字串的机器数的过程就称为编码。无符号数没有原码、反码和补码一说。只有带符号数才存在不同的编码方式。

    至于为什么计算机最终选择补码来表示呢?具体看这里

http://sharecourse.upln.cn/courses/c_809_04/theory/module_2/pdf/whybm.pdf

    从原码转成补码也看上面的文章。

    这里有一点很重要的,就是从补码怎么转为原码或者真值呢?

    其实这个过程跟从原码转成补码是一样的。这一点很多学习资料都没提到。我是在

http://wenwen.soso.com/z/q110390792.htm这里看到的。

        

         具备了以上知识后,现在来解释一下补码的范围是怎么回事。

1 先从简单的开始,正数的范围,明显补码的二进制范围是从00000000到01111111。那么取几个特殊的值来看看,

0000,0000

0111,1111

这两个二进制的数是谁的补码呢?

也就是(0000,0000)的真值是?

(0111,1111)的真值是?

由于正数的补码跟真值是一样的,

所以(0000,0000)的真值是0,(0111,1111)的真值是127。

由此可见,用补码来表示正数,取值范围是0-127。

 

2 负数的范围,明显补码的二进制范围是从10000000到11111111。再取几个特殊值来看看,

那么10000000的真值是?

10000001的真值是?

11111111的真值是?

上面有说过如何从补码转为真值。

计算后,发现

10000000的真值是(-1000,0000)=-128

10000001的真值是(-111,1111)=-127

11111111的真值是(-000,0001)=-1。

所以用补码表示负数,范围是-128到-1。

 

这里,特地,演算一下。(采取先不管符号位的做法)

10000001(这是补码)

取反,得 (111,1110)

+1,得(111,1111)

加上符号位(-111,1111)即-127

 

(1000,0000)(这是补码)

取反,得(111,1111)

+1,得(1000,0000)

加上符号位,得 –1000,0000,即是-128。

 

 

那么我们验证一下真值-127的补码形式是不是(1000,0001)。

-127这是真值,即(-111,1111)

转为原码(1111,1111)

取反,转为反码(1000,0000)(符号位不变)

+1,(1000,0001)(符号位不变)

 

再验证一下真值-128的补码形式是不是(1000,0000)。

-128(-1000,0000)显然原码表示不了。

只能这么理解法,

先不管符号位,得(1000,0000)。

取反,得(0111,1111)

+1,得(1000,0000),7位溢出了,去掉进位得(000,0000)

补上符号位得(1000,0000)。

其实,我们只要记住真值-128的补码形式是(1000,0000)就好了。

 

其实,求反加1的方法是有缺陷的,并不是补码的定义,了解了补码的定义,才可以真正了解补码与真值的转换。

 

就是利用同余。http://sharecourse.upln.cn/courses/c_809_04/theory/module_2/pdf/whybm.pdf

在数学中,用“同余”概念描述上述关系,即两整数 A、B 用同一个正整数 M (M 称为

模)去除而余数相等,则称 A、B 对 M 同余,记作:

A=B (MOD M)

具有同余关系的两个数为互补关系,其中一个称为另一个的补码。当 M=12 时,-

5 和+7,-4 和+8,-3 和+9 就是同余的,它们互为补码。

从同余的概念和上述时钟的例子,不难得出结论:对于某一确定的模,用某数减去

小于模的另一个数,总可以用加上“模减去该数绝对值的差”来代替。因此,在有

模运算中,减法就可以化作加法来做。

 

可以发现,有个技巧,互为补码的两个数加起来刚好等于模。

 

对于8位得二进制数,模等于2的8次方=256。

真值-127的补码是谁呢?

-127等价于 加上模减去127的差,即加上 129(1000,0001)。

因此-127与129(1000,0001)互补。

即真值-127的补码为(1000,0001),这个补码看起来是正数,其实表示的是负数。

 

现在再来看看真值-128的补码形式是不是(1000,0000)。

显然,-128等价于加上 256-128=128,即(1000,0000)。

 

触类旁通,真值-126的补码是?

-126等价于加上256-126=130,即(1000,0010)。

 

上面是,由真值求补码。

那么怎么由补码求真值呢?

 

比如补码(1000,0010)的真值是?

显然(1000,0010)=130,符号位是1,表示的真值是负数,

130-256=-126。

 

补码(1000,0000)的真值是?

显然,(1000,0000)=128,符号位是1,表示的真值是负数,

128-256=-128。


夜已深,先了解到这一步,以后有更深入的理解再来总结更新。

 

 

 

 


1 1
原创粉丝点击