补码的回顾以及补码发明的思路推演思考

来源:互联网 发布:红蜘蛛教学软件官网 编辑:程序博客网 时间:2024/05/16 02:00

补码与求补运算的定义

N个二进制位,M=N-1
通过一种编码映射。100...00 - 111...11 表示 (-2^M) - (-1) ; 000...00 - 011...11 表示 (0) - (2^M - 1)

对于编码A的求补 f(A) = (2^N)- A

原码转化成补码:

对于正数和零,原码即是补码
对于负数A,一般理解方法:
先做反码,然后编码意义上加1


求补运算的意义:

换言之,若要对一个数A求反,对那个数的补码A1做一次求补运算f(A1),所求的补码B1就是原来数A的相反数B的补码。

这里提供原码转化成补码另外一个理解方法
对于求负数A的补码
本质上,负数A的相反数B,B是正数,B的原码B1就是B的补码,A的补码就是f(B1)


---

机器实现:

x-y = x-1-y+1 = (x-1) - y + 1
在补码的转码中,这里的x=2^N 
这里的(x-1) - y即使对y进行反码操作,在ALU中可以N位同时刷新

至于N位整数+1,有一定的进位延时。

---
边界情况:
容易看到,我们对-2^N求反,仍然是-2^N
对2^N-1求反,则是-(2^N)-1

---
利用补码这种编码性质
f(y) = -y

x + y = x + y
x - y = x + f(y)

---

马后炮:事后猜测补码发明的思路, 从而看补码的优势

先看正码表示,设N=4, -1 = 1001; -2 = 1010, -1 > -2, 但是 1001 < 1010,两种映射的编码的序性不一致
反码呢,-1=1110, -2 = 1101,  Ok,序性正确了,
然而,这里有一个问题,就是正数与负数之间,有一个1的缝隙。-1=1110, 1=0001,从循环编码的角度,这两个编码相差3:1110->1111->0000->0001。
因为正零和负零是两个数,导致两个数系的断裂。怎么办?让负数整体往正数靠拢,迈进一步(+1),负1没有了。
这就是求补的过程了。反码再加1。

我想,当初写出计算机的编码设计论文的大牛(好像是图灵还是什么的),当然有更深的考虑。但从序性和数系联系的角度,补码的发明是相当合理的。而这种合理性,我个人认为,正是其优点。

从机器实现的角度,并不算复杂,但相对反码的机器实现,还是多了+1的进位延时。

---
int与unsigned int的思考
顺便,我也整理一下这里的误区。
如果声明变量a为int,但是却当作unsigned int,如果正常累加超出范围,转化成unsigned int结果应该还是可信的。
不过算了,我们利用好转换和保证类型的一致,这些底层的问题我们确实还是当作透明为好。

---

欢迎探讨。

Regards,
Junhao Li
edwin.jh.lee@gmail.com

---
From http://blog.csdn.net/qq_21311279/article/details/39585597

0 0
原创粉丝点击