数值的符号位加上其真值的绝对值,范围是[-127,127],也就是二进制的[11111111,01111111]
(记住,单个字节是8个bit,首位是符号位)
00010000>取反>00010000
10010000>取反>11101111
00010000>取反>00010000>取补>00010000
10010000>取反>11101111>取补>11110000
注:源码可以直接转化为10进制数(注意符号位),补码不能直接转化为10进制
注2:负数补码加其源码等于0,因此二进制下补码可以直接进行二进制运算,得到的结果直接转化成10进制就是答案
update:2019.10.10
建议将上面的源码,补码,反码的定义和计算方式记牢用熟后再看下面的,以免结构层次混乱
但这时问题就出来了,既然已经有了源码,要反码和补码干甚?
想一下,当两个用源码表示的数进行加或减运算,电脑还要判断是加法还是减法,还要判断是正数还是负数,两个字,麻烦
而且如果直接让源码相加,加出来的数是个什么你都不知道
1 - 1 = 1 + (-1) = [00000001]原 + [10000001]原 = [10000010]原 = -2
但如果用反码,就可以让符号位直接参与加减,同样减去一个数等于加上其相反数,那么判断正负和加减这两个步骤就减去了
1 - 1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原= [0000 0001]反 + [1111 1110]反 = [1111 1111]反 = [1000 0000]原 = -0
这样的话,就可以方便的计算出结果
但反码的0就会有1000 0000和0000 0000两种表示方法,于是就出现了补码
8位2进制下源码表示的数据范围是 [ 11111111 , 01111111 ] [1111 1111,0111 1111] [11111111,01111111],即十进制的 [ − 127 , + 127 ] [-127,+127] [−127,+127],而补码的是 [ − 128 , 127 ] [-128,127] [−128,127],因为补码的 − 128 = − 1 + ( − 127 ) = 10000001 + 11111111 = 10000000 -128=-1+(-127)=1000 0001+1111 1111=1000 0000 −128=−1+(−127)=10000001+11111111=10000000,在形式上就是二进制的 10000000 1000 0000 10000000,而原码的 10000000 = − 0 1000 0000=-0 10000000=−0, 00000000 = 0 0000 0000=0 00000000=0,就浪费了一个数据
因此,用补码可以解决效率问题,还可以多一个内存空间,这就是计算机里保存数据为什么要用补码而非源码(反码实质上只是一个过渡)
既然上文已经说了,补码是二进制运算的工具,源码是十进制与二进制的桥梁,那么补码的运算有什么规律?
[x]补+[y]补=[x+y]补
补码减法上文已经提到过转换方式
补码的乘法不具备 [ X ∗ Y ] 补 = [ X ] 补 × [ Y ] [X*Y]补=[X]补×[Y] [X∗Y]补=[X]补×[Y]补的性质。但是 [ X ∗ Y ] 补 = = [ X ] 补 × Y [X*Y]补==[X]补×Y [X∗Y]补==[X]补×Y,所得结果再取补码,如 x = 101 , y = 011 , [ x ∗ y ] 补 = − [ ( − 101 ) ∗ 011 ] = − [ 011 ∗ 011 ] = − 01001 = 10111 x=101,y=011,[x*y]补=-[(-101)*011]=-[011*011]=-01001=10111 x=101,y=011,[x∗y]补=−[(−101)∗011]=−[011∗011]=−01001=10111
A 43
B -85
C -43
D -84
(noip2017初赛第2题)
解析:
补码=源码的反码加1,故我们可以推出源码为11010101,转化为十进制为
− ( 2 0 + 2 2 + 2 4 + 2 6 ) = − ( 1 + 4 + 16 + 64 ) = − 85 -({2}^{0}+{2}^{2}+{2}^{4}+{2}^{6})=-(1+4+16+64)=-85 −(20+22+24+26)=−(1+4+16+64)=−85
选B