正数取反是先将初始数值转换成二进制数(6==》00000110),再对二进制数的每一位取反:即将0变为1、将1变为0。(00000110==》11111001),得到的是最终结果的补码,要转换为最终结果的原码则需再次取补码,就能得到计算结果;负数取反是先将初始数值转换成二进制数(以-6为例,10000110),再取得二进制数的补码,之后对补码的每一位取反:即将0变为1、将1变为0。得到的是最终结果的补码,要转换为最终结果的原码则需再次取补码,就能得到计算结果。
补码:正数的补码等于它的原码;负数的补码等于反码+1
# include <stdio.h>
int main()
{
unsigned char a=18,b;b=~a;printf(“~a=%d”,b); return 0;
}
运行结果为: ~a= 237
#include <stdio.h>
int main()
{
char a=18,b; b=~a;printf(“~a=%d”,b); return 0;
}
运行结果:-19
注意:
前一个程序结果很好理解,后一个因为a是带符号数据,因此~a=(11101101)2的结果是一负数的补码,转换为原码时,第1位符号位不变,对剩余的部分先减1,再全部取反,因此得到的二进制原码为:10010011,即十进制的-19。
在计算机中操作的是补码
对6取反(~6)
6的原码 0000 0000 0000 0000 0000 0000 0000 0110
6的反码 0000 0000 0000 0000 0000 0000 0000 0110
6的补码 0000 0000 0000 0000 0000 0000 0000 0110
计算机只能对补码操作,那么对6取反(~6),实际操作的是补码,每位取反
6的补码全部取反 1111 1111 1111 1111 1111 1111 1111 1001 (得到的这个数是最高为代表负数)
补码–>反码 -1 1111 1111 1111 1111 1111 1111 1111 1000
反码–>原码 取反 1000 0000 0000 0000 0000 0000 0000 0111
故~6=-7
已知补码如何求原码(真值)~
正数的补码反码与原码相同。
若已知补码为 1111 1000,如何求其原码呢?
(1)方法1:求负数 原码--->补码 的逆过程。
注意:符号位保持不变!
(A)先 - 1,得到 1111 0111
(B)取反(符号位保持不变,其他位置按位取反 ),得到 1000 1000
(2)方法2:
注意:符号位保持不变!
(A)将这个二进制数中(即 1111 1000),除了符号位,其余位置按位取反,得 1000 0111
(B)+ 1,得到 1000 1000
总结:
-1 后,再取反 和 取反后,再+1 的效果是一样的。
这就和 -(3-1) 和 (-3 +1) 是一个道理。