计算机原码、反码、补码、移码
在计算机里面,为了满足四则运算的要求,规定了原码、反码、补码,
为了数值之间大小的相互比较及一些格式数据记录的方便,而规定了移码.
原码:
数字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对应的码位是相同的.