为什么对Java中的负数取绝对值结果不一定是正数?

文章讨论了Java中Integer取绝对值可能出现负数的情况,源于Integer类型的取值范围限制。解决方法是在计算绝对值前将整型转换为long类型以避免溢出。同时介绍了Java整型的不同范围及其潜在的溢出问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

回答:

假如,我们要用Math.abs对一个Integer取绝对值的时候,如果用如下方式:

Math.abs(orderId.hashcode());

得到的结果可能是个负数。原因要从Integer的取值范围说起,int的取值范围是-2^31—(2^31)-1,
即-2147483648至2147483647
那么,当我们使用abs取绝对值时候,想要取得-2147483648的绝对值,那应该是2147483648。但是,2147483648大于了2147483647,即超过了int的取值范围。这时候就会发生越界。
2147483647用二进制的补码表示是:01111111111111111111111111111111
这个数+1得到:10000000000000000000000000000000

这个二进制就是-2147483648的补码。


虽然,这种情况发生的概率很低,只有当要取绝对值的数字是-2147483648的时候,得到的数字还是个负数。

那么,如何解决这个问题呢?

既然是因为越界了导致最终结果变成负数,那就解决越界的问题就行了,那就是在取绝对值之前,把这个int类型转成long类型,这样就不会出现越界了。


如,前面我们取值逻辑修改为

 Math.abs((long)orderId.hashCode());

扩展知识

整型的取值范围

Java中的整型主要包含byte、short、int和Iong这四种,表示的数字范围也是从小到大的,之所以表示范围不同主要和他们存储数据时所占的字节数有关。


先来个简单的科普,1字节=8位(bit)。java中的整型属于有符号数。
先来看计算中8bit可以表示的数字:
最小值:10000000(-128)(-27)最大值:01111111(127)(2^7-1)

整型的这几个类型中

  • byte:byte用1个字节来存储诸,范围为-128(-27)到127(27-1),在变量初始化的时候,byte类型的默认值为0。
  • shot:shot用2个字节存储,范围为-32,768(-2^15)到32,767(2^15-1),在变量初始化的时候,short类型的默认值为0,一般情况下,因为Java本身转型的原因,可以直接写为0。
  • int:int用4个字节存储,范围为-2,147,483,648(-2^31)到2,147,483,647(2^31-1),在变量初始化的时候,int类型的默认值为0。
  • Iong:1ong用8个字节存储,范围为-9,223,372,036,854,775,808(-2^63)到9,223,372,036,854,775,807(2^63-1),在变量初始化的时候,1ong类型的默认值为0L或0l,也可直接写为0。

超出范围的情况

上面说过了,整型中,每个类型都有一定的表示范围,但是,在程序中有些计算会导致超出表示范
围,即溢出。如以下代码:
 

int i Integer.MAX_VALUE;
int j Integer.MAX_VALUE;
int k =i+j;

System.out.println("i(”+i+”)+j(”j+”)=k(”+k+”)”)


输出结果:i(2147483647)+j(2147483647)=k(-2)


这就是发生了溢出,溢出的时候并不会抛异常,也没有任何提示。所以,在程序中,使用同类型的数据进行运算的时候,一定要注意数据溢出的问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值