一、计算机该怎么做减法?
比如2-1=1,1-1=0.由于种种原因(精力有限,暂不深究),加法电路难度和成本已经很高了, 当时的条件下,再去设计一个减法电路,费力又费钱,前辈们想用加法电路来解决减法运算问题。思路如下, 熟悉的可以跳过。
假设当前时针指向8点,而准确时间是5点,调整时间可有以下两种拨法:
一是倒拨3小时:8-3=5
二是顺拨9小时:8+9=12+5=5
可以看出在以模为12的系统中,减3和加9效果是一样的,因此减3运算,可以用加9来代替。对“模”12而言,3和9互为补数(二者相加等于模)。
“模”是计量器产生“溢出”的量。
从上面的事例中,我们可以得出结论,即在有模的计量系统中,减一个数等于加上它的补数(可以看下面的实例)。这就可以将减法运算转化为加法运算,达到用加法电路来解决减法运算的目的。
例如:减3和加253是一样的,8-3=8+253=256+5=5(对应的二进制数是[0000 0101]),就是说-3用253来表示,可以得到正确结果。这就是计算机做减法的思路。
二、这种算法的结果永远是正数。新的问题是 3-8=3+(256-8)=3+248=251,
显然3-8=-5。这种小的数字减去大的数字该怎么办?
例如3-8=3+(256-8)=3+248=251(对应的二进制码是[1111 1011]),但是很显然,我们想要的是 [1111 1011]=-5。那我们有两种选择,一种是保留这种处理减法的思路,就让[1111 1011]=-5,然后再找其他的二进制码表示251。另外一种是放弃这种处理减法的思路,确认[1111 1011]=251,并且找其他的二进制码表示-5。
不管是哪种选择都必须舍弃一个数字,-5和251不能同时存在,有没有发现byte中没有正128,只有-128?我们可以算一算,-5到-1是5个数,0算一个数,1到251是251个数,总共就有5+1+251=257个数,这可不行。因为8位二进制码最多只能表示256个数,如果-5和251都要表示,就会有257个数(不要少算了0),超出了表示范围。同理,-1和255 只能选一个,-2和254只能选一个,··· ,-128和128也只能选一个。
最终,为了避免2-3=2+(256-3)=255[1111 1111] 这样的尴尬。我们确定将[1111 1111]定义为-1,而不是255,同理,[1111 1110]不再是254,定为-2。类推下去,0-128=-128,但是按原先的算法,0-128=0+(256-128)=128[1000 0000],尴尬了,因此128也光荣牺牲了,把[1000 0000]让位给-128,
至此java中byte的范围确定为-128~127,而不是-127~128。