详解byte的范围:一个神奇的圈搞定-128是怎么来的

有这样一个思考题:

byte是有符号整数,最高位是符号位,有效数字位只有7位,用二进制原码表示其范围为:11111111 ~ 01111111,换算成二进制是-127 ~ 127,所以byte的范围是[-127 ~ 127]。

但是,这个结论,对吗?

显然是不对的,众所周知,byte表示的范围是-128~127

但是,-128是从哪里来的呢?

这和计算机存储数字的方式有关,计算机并不是直接存储数字的二进制原码,而是以补码的形式进行存储。

本文以byte类型为例,通过详细分析其范围,深入理解补码。

一,原码、反码、补码

在深入补码之前,我们先回顾一下原码、反码和补码的概念,它们是计算机表示负数的关键。

  • 原码:直接将数值转换为二进制,最高位用作符号位,0表示正数,1表示负数。例如,+5的8位原码是00000101,而-5则是10000101

  • 反码:负数的反码是在其原码基础上,除了符号位以外的所有位取反(0变1,1变0)。+5的反码仍是原码,而-5的8位反码是11111010

  • 补码:补码是反码加1。对负数而言,补码是其反码加1的结果。因此,-5的8位补码是11111011。补码的引入简化了计算机中的加减运算,使得加法运算可以统一处理正数和负数。

二,Java中的byte与补码

Java的byte类型使用补码来表示所有的数值,包括负数。

为了方便理解,考虑到byte表示的整数是有限的,我们用一个圆圈来辅助理解,假设圆每隔一个固定的距离的点代表一个byte数值。

1,正数在圆上的位置

因为正数的补码就是原码,所以先确定正数在圆上的位置,byte类型正数最小值是+0,补码是原码0000 0000,因为最高位是符号位,所以正数最大值是 0111 1111,即127。

在这里插入图片描述

2,负数在圆上的位置

确定负数在圆上位置的时候,要注意,负数的补码要通过原码、反码计算得到,比较麻烦,我们可以通过如下Java API来获取数字的补码(注意:打印出来的是Integer的补码,最右边8位是byte补码):

byte b = -1; // 最小的byte值
System.out.println("-1的补码: " + Integer.toBinaryString(b));

在这里插入图片描述

从上面圆上可知,数字0左侧是负数,第一个负数是-1,根据上图调用API的结果线上,-1补码是1111 1111

因为正数最大值是127,假设最小值是 -127,根据上述API,-127的补码是1000 0001
在这里插入图片描述

很明显,-127的补码1000 0001尾数是1,还可以减1,得到二进制1000 0000,这个二进制非常特别,我们找不出其对应的反码和原码。1000 0000减1的结果是最大值127的补码0111 1111,加1的结果是-127的补码1000 0001

在这里插入图片描述
把这个补码1000 0000对应的真值定为 -128,这是篇首问题(-128是怎么来的)的答案,byte的范围是[-128, 127]就是这样确定下来的。

在这里插入图片描述

三,补码的应用与注意事项

补码不仅简化了计算机中负数的运算,还解决了原码和反码中存在的一些问题,比如多个0的表示(在原码和反码中,+0和-0都被表示为全0,而补码中只有唯一的0)。此外,补码的使用使得加法运算可以统一处理正数和负数,无需区分加数的正负,极大地提高了运算效率。

在编写涉及byte类型数据的Java程序时,需要注意其有限的数值范围,避免超出界限导致的数据溢出错误。例如,对一个byte类型的变量进行运算时,如果结果超出了-128至127的范围,Java会自动将结果截断,只保留低8位,这可能导致意外的结果。

  • 12
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小手追梦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值