byte的范围为何是-128~127,而不是-127~128?

 一、计算机该怎么做减法?
    比如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。


 三、按照一的说法,-127和+129的效果等价,补码刚好印证了这一点:-127原码1111 1111,反码:1000 0000,补码:1000 0001。有木有发现抛开符号位的说法,1000 0001本来就是129,我们只是人为的把1000 0001规定为-127。知道这一点,求补码就是秒杀,例如:-1和255等价,那-1的补码就是255 =1111 1111 。验证一下:-1原码:1000 0001 ,反码:1111 1110,补码:1111 1111。继续推演,-128的效果和+128等价,那么-128就是128:1000 0000
那些说1000 0000是负零的怕是要多查查资料了。现在会发现,在补码中所有1开头的数,1000 0000 本是 128,实际表示的是-128,1000 0001 本是129,实际表示的是-127,同理1111 1111 本是255,实际表示的是-1,那么-1的补码是1111 1111是不是就不那么难理解了。

 问题补充:
  1.那原码、反码、补码的概念是拿来干什么的?
    答:现在唯一的问题是,用户输入-5后,计算机怎么得到[1111 1011]并保存。根据上面的理论,-5的补码就是
    256-5=251[1111 1011],但问题是我们正在解决减法问题,现在计算机还不会做减法,计算机怎么得到[1111 1011],
    于是先辈们发明了一种算法,先得出原码[1000 0101],然后符号位不变,其余位取反(逻辑非), 得到反码[1111 1010],再加一,得到了[1111 1011]。就是说,原反补码可以跳过计算直接得出2进制码。

2.计算机为什么不用原码表示负数?
  答:一是原码的作用本来就不是保存负数,而是便于我们理解。
  二是因为原码做减法得到值是错误的。在减法计算中,2-1=[0000 0010]原+[1000 0001]原
  = [1000 0011]原=-3,结果是不正确的。编码不仅要能表示数字,还要求运算结果和10进制不矛盾。
2.1计算机为什么不用反码表示负数?
  答:和原码同理,用反码也不能做减法:
  2-1=2+(-1)=[0000 0010]原+[1000 0001]原= [0000 0010]反+[1111 1110]反=[0000 0000]反=[0111 1111]原= 127。(符号位也参与运算)
2.2 那补码可以做减法吗?
  答:2-1=2+(-1)=[0000 0010]原+[1000 0001]原= [0000 0010]反+[1111 1110]反
   = [0000 0010]补+[1111 1111]补 = [0000 0001]补 =1。
   就是说只有补码可以做减法。所以计算机中采用补码来表示负数。
3 那8位二进制补码具体对应的10进制是多少?
  答:
     1000 0000 ...  -128
     1000 0001 ...  -127
          ...  ...  ...
     1111 1110 ...  -2
     1111 1111 ...  -1
     0000 0000 ...  0
     0000 0001 ...  1
     0000 0010 ...  2
     ...       ...  ...
     0111 1110 ...  126
     0111 1111 ...  127
     
3.1 那[1000 0000]补为什么表示-128?
   答:上面已经解释了,这里只做验证推理。[1000 0000]补不管是什么值,
   [1000 0000]补+[0000 0001]补=[1000 0001]补是恒成立的,

    一步一步转化:  [1000 0000]补+[0000 0001]反(正数原反补相同)=[1000 0000]反
     再转化:  [1000 0000]补+[0000 0001]原=[1111 1111]原
     再转化:  [1000 0000]补+ 1 = -127
     很明显:[1000 0000]补=-128。
3.2 为什么是-128~127,而不是-127~128了?
    答:如果是-127~128了,你会发现0-128=128。


3.3 网上有说因为-128和128同余,所以-128的补码是128,对吗?
   答:首要问题不是-128的补码是多少,而是总共只有256个数,-128和128只能选一个,两个都存在不就是257个数了吗?

4.那教材上说原码中出现正0和负0又是怎么回事?
   答:国内教材的狗屁理论。
   
5. 请问8位、16位、32位、64位cpu都是什么时间问世的?
  答:1979年6月1日 INTEL发布了8位元的8088微处理器。
      1978年6月8日: INTEL发布其16位微处理器8086。
      1985年10月17日,x86系列CPU Intel 80386发布。80386的广泛应用,将PC从16位时代带入了32位时代。
      2003年才以x86-64和64位PowerPC处理器架构的形式引入到个人电脑领域的主流。
有待研究的问题:
 1   -128的原码、反码各是多少?
 2 计算机不可能懂-5,那我们点击“-”、“5”这两个键,cpu是否直接接受到了-5的源码了?


 大神1
 
 大神2
 
 大神三

  

猜你喜欢

转载自blog.csdn.net/zhangjin1120/article/details/81274647