zoukankan      html  css  js  c++  java
  • 神奇在 Double 转换异常

    异常

    线上收到告警, 有以下异常

    java.lang.ArithmeticException: input is infinite or NaN
            at com.google.common.math.DoubleMath.roundIntermediate(DoubleMath.java:59)
            at com.google.common.math.DoubleMath.roundToLong(DoubleMath.java:156)
    
            .......................
    

    代码

    对应的业务代码如下:

    public static Long formatLongDefaultNegativeOne(Object obj) {
            String objStr = String.valueOf(obj);
            return !StringUtils.isBlank(objStr) &&
                   !objStr.equals("NaN") && 
                   !objStr.equals("Infinity") && 
                   !objStr.equals("null") ? 
                        DoubleMath.roundToLong(Double.valueOf(String.valueOf(obj)),  RoundingMode.HALF_EVEN) : 
                        -1L;
        }
    

    抛出异常的地方做了如下判断:

    ......
        if (!isFinite(x)) {
          throw new ArithmeticException("input is infinite or NaN");
        }
    ......
    ......
    //判断是否在有限范围内
    static boolean isFinite(double d) {
        return getExponent(d) <= MAX_EXPONENT;
    }
    

    getExponent(d) 是获取当前 double值的指数 . MAX_EXPONENTDouble最大值的指数 .

    getExponent(d) 的方法注释中有以下说明:

    If the argument is NaN or infinite, then the result is Double.MAX_EXPONENT + 1.

    If the argument is zero or subnormal, then the result is Double.MIN_EXPONENT -1.

    判断不在有效范围内的, 只有两种情况 , double 值是 NaNInfinity .

    分析

    主要逻辑都在这行代码中:

    DoubleMath.roundToLong(Double.valueOf(String.valueOf(obj)))
    

    从上面的异常中可以得知 , DoubleMath.roundToLong方法得到是 NaNInfinity . 即 Double.valueOf() == NaN || Double.valueOf() == Infinity .

    业务方法的这个代码 formatLongDefaultNegativeOne(Object obj) 是从上游获取的数值 , 业务上已经限定了只能是数值类型. 对于从上游得到的数值 , 理论上是只有这几种情况了.

    • null
    • NaN
    • Infinity
    • 正常数值

    对于前三种 , 逻辑上已经做了判断 , 但结果还是抛出了异常 . 说明数值不在上面四种情况里 .

    当前也没有想法具体是什么样的数值才能导致这个异常 . 由于缺少线上数据的支撑 , 无法继续下去 . 只能后面再解决定位了.

    未完待续.......

    后记

    线上加了日志, 才终于发现了问题。

    这个数据是 -Infinity 。 是负无限 !

    本应是正数计算的逻辑里, 竟然出现了负数。 所以一直也没往负数的方向上去想。

    找到问题就好解决了 。

    • 解决业务里出现负数的业务逻辑
    • 不兼容负数场景 , 但要有个 try - catch 。

    这个神奇的异常算是结束了。 同时也做了个警醒 , 对待无限 , 有正无限, 还有负无限!


    如果文章有帮助到您,请点个赞,您的反馈会让我感到文章是有价值的

  • 相关阅读:
    Shared Memory in Windows NT
    Layered Memory Management in Win32
    软件项目管理的75条建议
    Load pdbs when you need it
    Stray pointer 野指针
    About the Rebase and Bind operation in the production of software
    About "Serious Error: No RTTI Data"
    Realizing 4 GB of Address Space[MSDN]
    [bbk4397] 第1集 第一章 AMS介绍
    [bbk3204] 第67集 Chapter 17Monitoring and Detecting Lock Contention(00)
  • 原文地址:https://www.cnblogs.com/ElEGenT/p/13159506.html
Copyright © 2011-2022 走看看