转载自:https://blog.csdn.net/zj15527620802/article/details/80362535
转载自:http://www.01happy.com/computer-true-code-complement-code/
感谢博主flysening、 陈杰斌的详细讲解!
首先提几个概念: 原码,反码,补码
原码是什么?
原码就是早期用来表示数字的一种方式: 一个正数,转换为二进制位就是这个正数的原码。负数的绝对值转换成二进制位然后在高位补1就是这个负数的原码
举例说明:
int类型的 3 的原码是 11B(B表示二进制位), 在32位机器上占四个字节,那么高位补零就得:
00000000 00000000 00000000 00000011
int类型的 -3 的绝对值的二进制位就是上面的 11B 展开后高位补零就得:
10000000 00000000 00000000 00000011
但是原码有几个缺点,零分两种 +0 和 -0 。很奇怪是吧!还有,在进行不同符号的加法运算或者同符号的减法运算的时候,不能直接判断出结果的正负。你需要将两个值的绝对值进行比较,然后进行加减操作 ,最后符号位由绝对值大的决定。于是反码就产生了。
反码是什么 ?
正数的反码就是原码,负数的反码等于原码除符号位以外所有的位取反
举例说明:
int类型的 3 的反码是
00000000 00000000 00000000 00000011
和原码一样没什么可说的
int类型的 -3 的反码是
11111111 11111111 11111111 11111100
除开符号位 所有位 取反
解决了加减运算的问题,但还是有正负零之分,然后就到补码了
补码是什么?
正数的补码与原码相同,负数的补码为 其原码除符号位外所有位取反(得到反码了),然后最低位加1.
还是举例说明:
int类型的 3 的补码是:
00000000 00000000 00000000 00000011
int类型的 -3 的补码是
11111111 11111111 1111111 11111101
就是其反码加1
最后总结一下:
正数的反码和补码都与原码相同。
负数的反码为对该数的原码除符号位外各位取反。
负数的补码为对该数的原码除符号位外各位取反,然后在最后一位加1
各自的优缺点:
原码最好理解了,但是加减法不够方便,还有两个零。。
反码稍微困难一些,解决了加减法的问题,但还是有有个零
补码理解困难,其他就没什么缺点了
喔日,说到这里,估计都晕了,举个栗子把。
5的原码是 00000000000000000000000000000101(四个字节,32位(byte))
5的原码和反码,补码都一样。
-5的原码是 绝对值转换成二进制位然后在高位补1就是这个负数的原码 ,10000000000000000000000000000101
-5的反码就是原码符合外取反得到反码11111111111111111111111111111010
-5的补码就是反码加一得到补码11111111111111111111111111111011
最后补充一句,负数一般用补码来计算。
计算机中数字都采用二进制来表示,正数容易理解,那么负数怎么表示呢?这里涉及到原码,补码和反码的知识,咋一看可能毫无头绪,但是只要记住计算机中有符号数都是用补码形式表示的这句话,后面理解起来就不难了。
先来理解下8位二进制数表示原理。从而可以延伸到32位,64位以及任意其他位数。
8位二进制正数表示范围
0000 0000 ~ 1111 1111 (0 ~ 255)
这个不难理解,那么如何表示负数呢?设计计算机的人就想,把最高位作为符号位,0表示正数,1表示负数。这样,8位二进制数表示范围就发生了变化:
负数:1 111 1111 ~ 1 000 0000 (-127 ~ -0) 正数:0 000 0000 ~ 0 111 1111 (0 ~ 127)
但是如果在计算机中这样表示负数,那么相加减就很不方便。试想 -1 + 1 = 0 ,换成二进制就是:
1 000 0001 + 0 000 0001 ------------- 1 000 0010
计算机计算出来结果就是1 000 0010,这个结果等于-2,不是等于0,如果要保证结果正确,就需要修改计算机做加法的方式,非常不方便。于是设计计算机的人员就想到一个好方法,采用补码形式来表示有符号数。简单的说-1不是用1 000 0001来表示,而是用补码1 111 1111来表示,我们再来看下采用补码形式的 -1 + 1 的结果
1 111 1111 + 0 000 0001 ---------------- 10 000 0000
因为是8位二进制数,所以舍弃最高位1,看下结果,非常完美,就是0
其实在上面的例子中,1 000 0001就是-1的原码,而1 111 1111就是-1的补码。这下原码和补码的定义就都有了。
那么补码怎么计算出来的呢?
1、正数:原码和补码一致 2、负数:原码取反,然后加1
例如求-1的补码:-1原码是1 000 0001,符号位保持不变,取反就是 1 111 1110 ,然后加1,就得到补码1 111 1111了。
大家会发现,-1的补码还可以这么求:1取反(包括符号位),然后加1,其实也能得到-1的补码。在程序中,求一个数的相反数,如果看到这样的写法 ~num + 1,其实就是这个原理了。我个人还是更喜欢直接用 -1 * num,这样更通俗易懂。