Java中负数的绝对值竟然不一定是正数

 更新时间:2021年07月29日 10:35:01   作者:Hollis Chuang  
这篇文章主要介绍了Java中负数的绝对值竟然不一定是正数,文中给大家提到Java 中怎么把负数转换为正数,需要的朋友可以参考下

绝对值是指一个数在数轴上所对应点到原点的距离,所以,在数学领域,正数的绝对值是这个数本身,负数的绝对值应该是他的相反数。

这几乎是每个人都知道的。

在Java中,想要获得有个数字的绝对值,可以使用java.lang.Math中的abs方法,这个类共有4个重载的abs方法,分别是:

public static int abs(int a) {
    return (a < 0) ? -a : a;
}

public static long abs(long a) {
    return (a < 0) ? -a : a;
}

public static float abs(float a) {
    return (a <= 0.0F) ? 0.0F - a : a;
}

public static double abs(double a) {
    return (a <= 0.0D) ? 0.0D - a : a;
}

以上4个方法分别返回int、long、float、double类型的绝对值,方法里面的逻辑也简单,无非就是整数直接返回,负数取相反数返回

所以,基于以上所有的知识,我们经常会直接使用Math.abs来对一个数字取绝对值。

在我们的代码中,也有很多这样的例子。

比如,我们需要用订单号做分库分表,但是订单号是字符串类型,所以,我们就需要取得这个字符换的hashCode,因为hashCode可能是负数,所以然后再对hashCode取绝对值,再用这个值去对分表数取模:

Math.abs(orderId.hashCode()) % 1024;

但是,上面这个逻辑是有问题的!!!

因为在极特殊情况下,上面的代码会得到一个负数的值。

**这个极特殊情况下就是当hashCode是Integer.MIN_VALUE,即整数能表达的最小值的时候,**可以代码验证下:

public static void main(String[] args) {
    System.out.println(Math.abs(Integer.MIN_VALUE));
}

执行以上代码,得到的结果是:

-2147483648

很明显,这是个负数!!!

为什么会这样呢?

这要从Integer的取值范围说起,int的取值范围是-2^31 —— (2^31) - 1,即-2147483648 至 2147483647

那么,当我们使用abs取绝对值时候,想要取得-2147483648的绝对值,那应该是2147483648。

但是,2147483648大于了2147483647,即超过了int的取值范围。这时候就会发生越界。

2147483647用二进制的补码表示是:

01111111 11111111 11111111 11111111

这个数 +1 得到:

10000000 00000000 00000000 00000000

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

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

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

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

如,前面我们的分表逻辑修改为

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

就万无一失了。

大家可以执行下以下代码:

public static void main(String[] args) {
    System.out.println(Math.abs((long)Integer.MIN_VALUE));
}

得到的结果就是:

2147483648

以上,就是今天要介绍的知识点了。

但是,一定要记得,对long类型取绝对值其实也可能存在这个情况哦!只不过发生的概率就更低了,但是只要他存在,就有可能发生哦!

ps:下面看下Java 中怎么把负数转换为正数?

要将负数转换为正数(这称为绝对值),请使用Math.abs()。此Math.abs()方法的工作方式如下:“number = (number < 0 ? -number : number);”。
看一个完整的例子:

package com.mkyong;
  
public class app{
   
  public static void main(String[] args) {
     
    int total =1 +1 +1 +1 + (-1);
     
    //output 3
    System.out.println("Total : " + total);
     
    int total2 =1 +1 +1 +1 + Math.abs(-1);
     
    //output 5
    System.out.println("Total 2 (absolute value) : " + total2);
     
  }
   
}

输出量

Total :3
Total2 (absolute value) :5

在这种情况下,Math.abs(-1)会将负数1转换为正数1。  

到此这篇关于Java中负数的绝对值竟然不一定是正数的文章就介绍到这了,更多相关java负数绝对值内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java动态数组ArrayList实现动态原理

    Java动态数组ArrayList实现动态原理

    ArrayList是一种动态数组,它可以在运行时自动调整大小以适应元素的添加和删除,在Java中,你可以使用ArrayList类来实现动态数组,本文将给大家介绍一下ArrayList动态数组,是怎么实现动态的
    2023-08-08
  • MyBatis-Plus联表查询(Mybatis-Plus-Join)的功能实现

    MyBatis-Plus联表查询(Mybatis-Plus-Join)的功能实现

    mybatis-plus作为mybatis的增强工具,简化了开发中的数据库操作,这篇文章主要介绍了MyBatis-Plus联表查询(Mybatis-Plus-Join),需要的朋友可以参考下
    2022-08-08
  • 实例详解Java库中的LocalDate类

    实例详解Java库中的LocalDate类

    在做报表统计时,需要对指定时间内的数据做统计,则需要使用到时间日期API,下面这篇文章主要给大家介绍了关于Java库中LocalDate类的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-01-01
  • Java正则表达式基础语法详解

    Java正则表达式基础语法详解

    这篇文章主要介绍了Java正则表达式语法,包括常用正则表达式、匹配验证-验证Email是否正确以及字符串中查询字符或者字符串,感兴趣的小伙伴们可以参考一下
    2021-10-10
  • 面试官:怎么做JDK8的垃圾收集器的调优(面试常问)

    面试官:怎么做JDK8的垃圾收集器的调优(面试常问)

    这篇文章主要介绍了面试官:怎么做JDK8的垃圾收集器的调优,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08
  • Spring之AOP两种代理机制对比分析(JDK和CGLib动态代理)

    Spring之AOP两种代理机制对比分析(JDK和CGLib动态代理)

    这篇文章主要介绍了Spring之AOP两种代理机制对比分析(JDK和CGLib动态代理),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-05-05
  • SpringBoot中将@Bean方法解析为BeanDefinition详解

    SpringBoot中将@Bean方法解析为BeanDefinition详解

    这篇文章主要介绍了SpringBoot中将@Bean方法解析为BeanDefinition详解,得到的BeanDefinition是ConfigurationClassBeanDefinition类型,会为BeanDefinition设置factoryMethodName,这意味着当实例化这个bean的时候将采用工厂方法,需要的朋友可以参考下
    2023-12-12
  • Spring与MyBatis集成 AOP整合PageHelper插件的操作过程

    Spring与MyBatis集成 AOP整合PageHelper插件的操作过程

    Spring与MyBatis集成的主要目的是为了提供更强大的数据访问和事务管理能力,以及简化配置和提高开发效率,这篇文章主要介绍了Spring与MyBatis集成AOP整合PageHelper插件,需要的朋友可以参考下
    2023-08-08
  • Java中多线程的ABA场景问题分析

    Java中多线程的ABA场景问题分析

    这篇文章主要为大家介绍了Java中多线程的ABA场景问题分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • spring data jpa分页查询示例代码

    spring data jpa分页查询示例代码

    本篇文章主要介绍了spring data jpa分页查询示例代码,分页在很多项目中都能使用,具有一定的参考价值,有兴趣的可以了解一下。
    2017-03-03

最新评论