最近又回头学习二进制,以前困扰的原码、反码、补码等概念清晰了许多。
做了如下总结,错了欢迎指正啊:
一、概念
原码、反码、补码是一种概念,计算机都是采用补码表示存储数据的,原码是早期用来表示数字的一种方式,可以理解为方便人去识别数字大小的一个东西,(总之,原码其实也不是真实存在的)。
正数:原码-反码-补码都一样。例如3的原码、补码、反码都是0000 0011
负数:
原码:最高位是符号位表示负数,其他位和正数的计算方式一样。比如1000 0010=-2
反码:对负数,最高位不变,还是1.其他位按位取反。例如1000 0010的反码=1111 1101
补码:对负数,补码=反码+1
以上只是概念的理解,也是之前的粗浅了解。导致看到补码计算实际值是,只能在用另外一个公式:补码的补码是原码了。
二、补码在计算机里的计算方式
这次我想从计算机的角度来剖析一下补码。
在计算机内,对于任何有符号类型,其最高位是符号位,而且有权重。
这个现象当时在学的时候就发现,但是没有引起重视,因为当时学习的书本上没说。
以8bit的有符号数为例。-3的补码1111 1101=-128+64+32+16+8+4+0+1=-3
+3 = 0000 0011 = 1+2 = 3
使用权重之后,可以在补码直接计算其结果,这就是计算机计算的方式。现在看来,这是个很简单的概念,只要当时在学的时候课本有提一下,也不会一直反码+1了。
计算补码的方式到这里其实可以了,记住每个bit0-7对应值1,2,4,8,16,32,64,-128然后去求和即可。
三、三个算补码的方法
例如:值x的补码是1111 1001,求x。
下面有3方法。
方法1:(用补码取反+1是原码的方式)
1111 1001反码:1000 0110
原码x=1111 1001的补码:1000 0111=-7
其实这里很容易把人搞晕,因为原码的时候最高位只是个负号,其没有权重。而补码却是有权重的。
方法2:(计算机存储原理)
1111 1001= -2^7+2^6+2^5+2^4+2^3+2^0=-7
方法2比较好理解,但是1多的时候,其实计算量也不少。
方法3:(针对方法2的改进)
把bit0对应的权重加起来再加1,取负号即可
补码1111 1001 = -(2^1+2^2+1)= -7
原理就是:N位二进制最高位和N-1位bit的关系。N-1位bit所有bit=1时+1 会进位,第N位=1,其他位是0.即2^n = 1+(2^0+2^1+2^2+...2^(n-1))
使用方法2的时候,把最高位使用该公式代入,可以消去全部bit为1的。
所以1111 1001 = -(2^1+2^2+1)= -7
这样算补码就更简单了.
四、按位取反。
一直没有说这个,因为说原码、反码、补码是没这个概念的,但是如果你后面接触编程语言的“~”,可能会把反码和按位取反弄混。
其实,这两个的概念完全不一样。
按位取反:对给定值的每一个bit取反。
比如上面正数3=0000 0011。按位取反,~3=1111 1100=-4
但是,反码其实还是0000 0011。
负数的时候很容易混淆。-3原码= 1000 0011,-3反码= 1111 1100
~(-3) = ~(1111 1101)=0000 0010 =2
其实就是最高位的处理,取反码的时候,负数最高位是不变的,恒定为1.
但是按位取反最高位一定会变化。