java byte最小值_关于java中byte取值范围最小值为什么是-128而不是-127引发的思考...

我们都知道java 的byte占4个字节,1个字节8位。而计算机表示数据都是以二进制的形式表示。那么一个byte表示的二进制应该为0000 0000 -1111 1111,又因为最高位代表符号位,那么一个byte表示的范围就应该为(-2^7-1)-(2^7-1)即-127到127怎么会有-128呢?

其实也没有什么好说的,这就是规定的,包括short,int,long这些都是一样!那么为什么这么规定呢?有兴趣的可以继续往下看。我们一步一步的分析:

1.计算机没有减法运算,所谓的做减法其实是通过加法来运算的。那么怎么将减法变成加法来运算呢?这里涉及到一个模的概念。通常的解释就是用的一个钟表来解释的。

172bcc15e09d62524c5c04904a6bec39.png

比如现在是3点钟,我们现在要让它指到1点,我们可以怎么办呢?有两种方式:

将时针往后拨两个小时即 3-2=1;将时针顺时针拨10个小时即3+10同样指向了1点。是否明白了一点呢,计算机将减法变成加法采用的主要就是这种方式!

那么计算机怎么将3-2变成3+10的呢,怎么求出这个10的呢。这里就涉及到了一个模,在这里这个模就是12。这个12在这个时钟中就代表最大值,通过12-2就是等于10了。当然刚说了计算机没有减法,这里自然不会是12-2这么算。需要清楚计算机怎么算的继续往下看:

我们都知道计算机里负数是以补码的形式存在的,正数的补码是其本身,计算机加法是补码相加。

这里需要重温一下:

负数的补码是其反码加1.负数的反码是除符号位外,其余位数安位取反。正数的补码,反码,原码均相同。那么我们来看看(byte)(3-2)这个在计算机里面是怎么计算的呢?我们这里是以byte来讨论的所以是以8位二进制来表示:

3->0000 0011(原/反/补)

(-2)->1000 0010(原)->1111 1101(反)+1->1111 1110(补码)

所以3-2=0000 0011+1111 1110(补码)按位相加=0000 0001(补码)(符号位相加溢出留0)

注意:补码相加时符号位进行了计算的。

上面的0000 0001就是3-2在计算机里保存的结果,还需要转换为原码,因为符号位是0代表正数,原码也是0000 0001所以显示为10进制就是1.

看了上面的过程,我们来梳理一下,计算机为什么要将负数保存为补码的形式。

我们之前看了关于时针的问题即3-2=3+10等于1点。

那么计算机将负数变成补码也是这个原因,希望通过与补码相加来将减法变成加法,因为计算机没有减法。

我们上面看了,时针的模是12那么byte的模是多少呢?我们可以通过计算获取,参照

3-2=1;

3+10=13;

那么根据时钟的模就是10+2等于12的计算方式:

同理计算机中: 3-2=0000 0011+1111 1110(补码)

其中0000 0011+1111 1110(补码)类比上面的3+10;

那么btye的模=1111 1110(补码)+0000 0010(2的原码)=1 0000 0000(2的8次方)=256,(注意此处没有区分符号位,因为计算机计算补码相加时符号位也是相加了的,需保持一致)这样在byte范围内计算结果才不会出问题。不过你会发现有9位了,对就是9位。但这并不影响因为它只是byte类型计算时用的模,只要byte类型的数值是在8位以内就行。

那么我们再反过来看,为什么时钟上 3+10=13与3-2=1相等了呢,显然是因为13再减去了个12即13-12(模)=1.

那么表现在计算机中就相当于溢出,即3-2=0000 0011+1111 1110(补码)按位相加=1 0000 0001(补码)然后舍去了1 0000 0000(模)(因为只有8位)=0000 0001(补码)。

其实模的值是先确定好了的。我们会发现模其实就是等于2的n次方,n代码数据类型的位数。那么我们就不难理解为什么负数的补码是原码的反码+1了,因为这样处理,补码加上无符号原码就刚好等于模即10000 0000(byte类型的模的二进制)

我们还可以根据上面推算出:补码=模-负数的绝度值

感觉有点跑题了。总之计算机将减法转换为加法的思想就是采用了模的思想!

那么我们继续看看为什么btye最小值是-128不是-127呢?

原因是:1000 0000 表示 -0 而又有0000 0000表+0

-0显然没有任何意思,那么就规定1000 0000表示成-2的7次方。这样还可以多表示一位。

那么用它表示-128来计算有没有问题呢,答案肯定是没有的,不然经过这么久了,怕是早就出问题了。但是为什么不会出现问题呢?

我们按平常的思路来看-128首先是个负数那么除符号位外取反+1再保留8位的补码是0000 0000

那么-128+1=0000 0000+0000 0001 = 0000 0001 =1

结果显然不对,为什么不对,因为既然1000 0000 表示-128我们肯定不能按平常思路来算 因为正常来算的话 11000 0000才应该表示-128.

问题出在了-128的补码计算方式上,我们可以根据上面的公式计算补码为:模-负数的绝度值。

既然为-128那么绝对值肯定为128。所以-128的补码为 1 0000 0000 - 1000 0000= 1000 0000 即其本身

那么此时 -128+1=1000 0000+0000 0001 = 1000 0001 (补码)

再转换成原码1111 11111显示出来即-127。结果正确 !

至此,结束,欢迎留言讨论!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值