首先,负数要在计算机中正确存储,其对应变量必须声明为有符号数。有符号数的最高位为符号位:0代表正数,1代表负数;后面的位则为数值位。
现在来研究一个简单的负数-1在一个字节(8位)中的存储。
按照一般理解,-1在计算机中应该为 1000 0001:最高位为符号位1,后面是数值1,这样的形式类似于十进制的数学表示。如果这时我们想做一个加法运算:
人的大脑很容易进行求解,但计算机这不一定。
按照这种类十进制数的编码方式,2在计算机中的表示为0000 0010,若直接进行加法运算,我们得到
1000 0011如果是有符号数,表示-3;如果是无符号数,表示131。很显然,用这种类十进制的编码方式,直接进行加法运算,根本得不到准确的答案。
聪明的科学家在一位的十进制数中发现了一种数值计算规律:
二位的十进制数
以此类推。
计算可拆分成两步:①2与正数9相加,或02与正数99相加;②舍弃最高位进位。
细心的我们会发现9和99分别与-1和-01对应的正数1和01相关,二个正数相加后刚好可以进一位,且其余的数值全为零,即9+1=10,99+01=100。我们称9是-1的补码,99是-01的补码。
十进制每一位都有9个数码:0~9。我们定义0的反码是9,1的反码是8,2的反码是7,3的反码是6,4的反码是5。也就是说,在每个位上,原始数与其反码数相加等于9。
例如54的反码45,二者相加等于99;623的反码376,二者相加等于999。很明显,要想得到补码,只需要在对应的正数反码上再加1即可。
这个计算规律对于二进制数而言,同样适用。
而且对于计算机而言,若数值超出存储位数溢出,溢出部分会被直接丢弃,所以第二步根本不用执行。
二进制每一位有2个数码:0,1,则0和1互为反码。
-1对应的正数为1(负数的模),1编码为0000 0001,取反码1111 1110,再加1得到1111 1111。
若把(-1)在计算机中编码成1111 1111,则可以直接用加法运算得到正确答案。
在计算机中,运算变换成二进制数形式:
这就是把-1(源码1000 0001)转成补码1111 1111的机理。
总结:负数求模→按位取反→加1。