Java中的负数的在计算机中的二进制表示,以及与十进制的相互转换

来源:互联网 发布:网络歌手家家 编辑:程序博客网 时间:2024/05/17 03:39
       我们知道数字在计算机中都是以二进制表示的,数字类型有:byte,short,int,long
       我给计算机一个数字,计算机首先要确定他的类型,因为不同类型占有的空间是不一样的,
           byte占有一个字节,总共8位,最高位是符号位,取值范围是-128-127
           short占有两个字节
           int占有4个字节
           long占有8个字节
       计算机中的二进制都是有符号位的二进制,所以对于一个byte类型的1111 1111,他是不能表示255的,首先我们看到最高位是1,他表示的是一个负数。
       这里还要说明一个问题,虽然二进制的最高位表示符号位,1对应负,0对应正,但是绝对不是像咱们想的,负数就是在正数的基础上,把最高位改成就可以了。当然正数就是最高位是0,其他位按照咱们知道的计算即可。
       那么负数到底是怎么表示的呢?为什么要这么不合我们常人的思维这样表示呢?
       你给计算机一个负的十进制数,电脑中表示的思路是:先得到它对应的正值的二进制表示,然后取反,再加一,得到对应的负数的二进制表示
       这也就是计算机中的补码表示法!!!
       计算机中计算这样一个式子:8-1,8是正数,直接用它的原码(正数的原码,反码,补码都是一样的),-1是负数,用的它的补码,然后8+(-1),对应位相加即可。
    这里如果按照都是byte类型来算的话:0000 1000 + 1111 1111((+1)0000 0001->(取反)1111 1110->(加一)1111 1111)= 0000 0111结果是7
       上述过程,就是计算机计算加减法的实现方法。
       对于如何由一个负数的二进制得到对应的十进制,是这样的:计算机得知这是一个负数的二进制,也就是最高位是1之后,先取反再加一,得到的是正值,去相反数也就是对应的负数的十进制表示。
       至于具体为什么会出现反码和补码,网上相关的帖子很多,大家可以看一下,首先有一个-0和+0的问题,是通过反码补码解决的,这里谨希望大家不要想当然的认为负数在计算机中的表示就是把对应的正数的最高位改成1,例如-1的表示是1111 1111,而不是1000 0001,这就是一个活生生的例子。

       为什么会想到分析这个问题,因为在写一个接受串口数据的程序的时候,遇到这个问题,具体如下:
       接受到的数据流,Java是将其存储到byte类型的数组中的,自然就会把最高位当成符号位,而我对于数据的组织并不是把最高位当成符号位,因此需要将符号位计算进数值中。开始的思路是直接将得到的负数取相反数,然后再加上128,也就是像上面的错误理解,负数是在对应的正数的基础上把最高位变成1。
       正确的做法应该是:
       首先明确一下,因为你要让最高位表示数值,而byte类型的第八位肯定要表示符号的,所以,必然要将类型转换成空间更大的,这里转换成int类型,因为int类型的第八位不是符号位了。要让1-8位表示数值,而且肯定是正数,也就是除了1-8位其他的都是0,包括符号位,然而实际情况是:在将byte直接转化成int之后,低8位不变,其他位全部是1(例如上面提到的-1的int类型表示为1111 1111 1111 1111 1111 1111 1111 1111),很简单,因为int类型的负数的表示也是用补码的,必然也经过取反加一的过程,所以高的24位全部变成1,要让他们变成0,很简单,按位与上一个0xff(0000 0000 0000 0000 0000 0000 1111 1111)即可。
       具体实现是int b = b1 & 0xff;




1 0