计算机原码、反码、补码、移码

在计算机里面,为了满足四则运算的要求,规定了原码、反码、补码,

为了数值之间大小的相互比较及一些格式数据记录的方便,而规定了移码.

原码:

数字x0x1x2...xn中x0表示符号位(0表示正,1表示负),x1-xn表示真值。

如:

1 = [0000 0001]原,                  2 = [0000 0010]原

如果将这两个正数相加,即0000 0001(2) + 0000 0010(2) = 0000 0011(2) = 3(10)

结果是正确的,所以在其表达范围内进行两个正数的加法都是可行的.

但是,如果进行减法运算呢?

如:

1 = [0000 0001]原,                  -2 = [1000 0010]原

如果将这两个数相加,即0000 0001(2) + 1000 0010(2) = 1000 0011(2) = -3(10)

明显这个结果是错误的,还可以证明减法运算的结果都将是错误的.

所以只有原码的运算是不够的.

于是如果将负数除符号位外的真值位取反再进行运算又会是如何呢?

即:-2(原) = 1000 0010(2)取反后得 1111 1101再与正数0000 0001相加 = 1111 1110

将该结果取反后得1000 0001即是10进制-1(10).这就是反码的作用,同时可以注意到反码的格式是:

正数不变,负数求反.

即:

数字x0x1x2...xn中x0表示符号位(0表示正,1表示负),x0=0时,x1-xn不变,x0=1时x1-1n求反。

如:

[0000 0001]原 = [0000 0001]反,                 [1000 0010]原 = [1111 1101]反

再看一些加减法运算:

1(10) + 1(10) = [0000 0001]反 + [0000 0001]反 = [0000 0010]反 = 2(10)                  正确

1(10) +(-2)(10) = [0000 0001]反 + [1111 1101]反 = [1111 1110]反 = -1(10)             正确

但是如果进行1-1的运算呢?

即:

[0000 0001]反 + [1111 1110]反               = [1111 1111]反 = -0(10)

也就是说0占了两个码位+0与-0用二进制反码表示为[0000 0000]反与[1111 1111]反.

而整个8bit的反码表示范围为-127 ~ -0及+0 ~ +127共256个码位255个数字(0用了两个码位).

为了弥补这个问题,后来规定将负数-1,这样范围补为-128 ~ -1及0~127,只有一个0了,补多了一个-128.

256个码位刚好有256个数字.

这样,就有了补码的概念:

正数不变,负数求反后+1.

如:

1(10) = [0000 0001]补,    

-1(10) = [1000 0001]原 = [1111 1110]反 = [1111 1111]补,

-2(10) = [1000 0010]原 = [1111 1101]反 = [1111 1110]补.

1(10) + (-1)(10) = [0000 0001]补 + [1111 1111]补 = [0000 0000]补 = [0000 0000]反 = 0(10)

1(10) + (-2)(10) = [0000 0001]补 + [1111 1110]补 = [1111 1111]补 = [1111 1110]反 = -1(10)

哈哈,这就是传说中的原码、反码、补码的概念,同时也可以看到一个规律:

原码、反码、补码的正数都是一样的!反码的负数是原码求反,补码的负数是反码加1,符号位不变!

在计算机里面都是补码的格式存储的,记录用区间表示为[-128,127]共有256个整数.

这样可以将符号位一起参加运算简化了运算规则,提高软件运行效率

减法运算用加法电路进行,简化硬件制作.

哈哈,科学就是这样进步的,不要看他们有先来后到,但在目前的计算机数据中他们都在不同的领域中

依然体现着独有的特色。

再来看一看移码又是什么东东。

首先是科学们发现原码、反码、补码在数据的大小比较的时候很不直观,如:

[1111 1111]补 < [0000 0001]补,前边那个全是1,后面那个数只有一个1,为什么反而前面那个要小。

为了解决这个问题,科学家们引入了移码;

在移码的表示方法中,最高位仍是符号位,其他位是真值位,

但不同的是,移码的最位为1是代为正数, 0时代表负数,它与补码的关系比较亲密:

(x0)x1x2x3...xn = (!x0)x1x2x3...xn,即将补码的符号位取反就是该数的移码。

再来看刚才的两个数用补码的不等式表示为:

[0111 1111]移 < [1000 0001]移,这样不就很直观了吗?

另外,移码通常被用来作浮点数的阶码。

例:原码、反码、补码、移码之间的相互转换,4bit有符号数表示如下

真值 原码 反码 补码 移码 0 #0000 #0000 #0000 #1000 1 #0001 #0001 #0001 #1001 2 #0010 #0010 #0010 #1010 3 #0011 #0011 #0011 #1011 4 #0100 #0100 #0100 #1100 5 #0101 #0101 #0101 #1101 6 #0110 #0110 #0110 #1110 7 #0111 #0111 #0111 #1111 #-0 #1000 #1111 #0000 #1000 -1 #1001 #1110 #1111 #0111 -2 #1010 #1101 #1110 #0110 -3 #1011 #1100 #1101 #0101 -4 #1100 #1011 #1100 #0100 -5 #1101 #1010 #1011 #0011 -6 #1110 #1001 #1010 #0010 -7 #1111 #1000 #1001 #0001

从表中可以看出在原码与反码中,+0和-0占用了两个码位.

而在补码和移码中+0各-0对应的码位是相同的.