在这里我们要先明白计算机的运算原理:高压电流代表1,低压电流代表0(低压电流在高压电流面前忽略不计)。
所谓的0+0,就是输入低压电流+低压电流,输出低压电流,所以0+0=0;
所谓的1+0,就是输入高压电流+低压电流,输出高压电流,所以1+0=1;
所谓的1+1,就是输入高压电流+高压电流,输出特高压电流,计算机检测到特高压电流,自动在下一根电路中输入高压电流,本电路电流改为低压电流,所以1+1=10;
所以从上述的计算机运算原理中明白,计算机中数的运算就是在输入端输入电流,在输出端检测电流,具体见图1。
图 1
所以,在计算机中并没有减法操作,计算机不可能输入负电流,而且也不可能从反方向输入电流,因为输入端和输出端已经确定。
所以,面对计算中的减法运算时,计算机通常把它转换为加法运算,下面我们来说明是如何转换的。
比如8 - 5 ,我们就可以转化成8 +(-5),这样我们就把它转换成加法运算了。
而8的二进制为0000 1000,-5的二进制为1000 0101(在计算机中,第一位是符号位,0代表正,1代表负,比如-8 = 1000 1000),这个时候我们把它们两相加。
0000 1000
1000 0101
--------------
1000 1101
而1000 1101的十进制是-13,这显然不是我们要的结果。
这个时候我们要换一种思路,以机械时钟为例(图 2 机械钟),机械时钟有12个刻度(所以机械时钟的模为12),当指针越过刻度12时,指针又从0重新开始(也就是所谓的12 = 0,这一步的专业术语是取模),我们称12为机械表的模,所以我们需要利用这一点,这样就能达到8加上一个数等于3这一目的,所以现在是要解决加多少的问题,下面是数学证明:
被减数 + x = 差
因为 被减数 = 减数 + 差
所以 减数 + 差+ x = 差
双方同时减去“差” 得 :减数 + x = 0
因为12 = 0 ,所以 减数 + x = 12
所以 x = 12 - 减数
所以得到定理:被减数 - 减数 = 被减数 + ( 12 - 减数)= 差
图2 机械钟
计算机的减法原理的灵感就来自于机械钟,机械表是每12就重新开始,那么在byte的模是多少呢,byte有8位bite,第一位是符号位,所以能表示数的大小的是后7位bite。 1000 0000 = 128,因为byte中能表示数的大小的是后7位bite,所以当数字在计算机中变为1000 0000时,后7位数为000 0000=0,数直接变成0,所以byte的模是128(1000 0000 = 128),所以x = 1000 0000(128)- 减数,但计算机中没有减数,所以我们要怎么求出x呢。在这里我们就要利用二进制的一个性质(二进制特有的反码性质),需要把一个二进制数取反(比如1000 0101取反后就是1111 1010,我们称取反后的结果为反码,取反时符号位是不变的,因为符号位不表示数的大小),那为什么要取反呢,下面是证明过程:
首先要证明反码和原码之间的关系
原码 000 0101
反码 111 1010
---------------------
111 1111
所以 111 1111
- 000 0101(原码)
-------------------------
111 1010(反码)
我们只要将原码与反码的和加上1,就能变成1000 0000,而1000 0000是byte的模。
然后利用反码和补码之间的关系求出x:
x = 1000 0000 - 减数(原码)
= 111 1111 + 1 - 减数(原码)
= 111 1111- 减数(原码)+1
= 反码 +1
所以在计算中规定了一个补码 x= 补码 = 反码 +1
补码和原码的关系是: 补码 = 模 - 原码
所以 差 = 被减数 + 减数的补码
所以,计算机规定,正整数的反码,补码等于原码;负数的反码为除符号位不变外,每一位数取反(0变1,1变0),补码为 反码 +1。
所以可以得到计算公式: 差 = 被减数的补码 + 减数的补码
为计算方便,当你输入一个负数时,计算机自动会将负数转换成这个负数的补码存储在计算机中,而正数的补码就是原码,所以就有计算机中存储的都是这个数的补码。
所以8 - 5 在计算机中的表达是 0000 1000 (8的补码)
1111 1011( -5的补码)
----------------------------
10000 0011
因为计算机会舍弃超出存储空间的部分,10000 0011 = 0000 0011
符号位为0,是正数,这也解释了为什么设计0代表正数,1代表负数,因为8(000 1000)比5(000 0101大,所以000 1000加上000 0101的补码结果一定会进1,所以最后符号位会变成0,结果位正数。
因为我们求的是补码的和,所以显示结果的时候要将它转化成原码, 0000 0011的符号位是0,正数,正数的补码就是它的补码,所以原码是0000 0011=3(证明过程见后面)。
下面我们要面对另一个问题,如果被减数小于减数怎么办,以5-8为例
根据计算公式 : 差 = 被减数的补码 + 减数的补码
5的二进制位补码是000 0101,-8的二进制补码是1111 1110。
0000 0101
1111 1000
---------------
1111 1101
因为我们求的是补码的和,所以显示结果的时候要将它转化成原码,那怎么转换成原密码呢。
从上面的计算可知: 补码 = 模 - 原码
所以 原码 = 模- 补码
原码=补码 + 补码的反码 + 1-补码
原码 = 补码的反码 + 1
所以可以看出,原码就是对计算结果求补码,所以1111 1101的补码为1000 0011=-3。