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 。

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


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

  • 相关阅读:
    [笔记][Java7并发编程实战手冊]3.8 并发任务间的数据交换Exchanger
    DOSbox汇编集成环境下的具体设置
    nginx的 CPU參数worker_processes和worker_cpu_affinity使用说明
    【数据压缩】LZW算法原理与源代码解析
    [javase学习笔记]-8.1 statickeyword之特点
    开源工作流CCBPM中关于解决谷歌等浏览器silverlight的问题
    “建议127:Lock与synchronized是不一样的问题”实际验证
    java线程同步问题——由腾讯笔试题引发的风波
    Centos6.5下安装protobuf及简单使用
    linux, configure --prefix=/有什么用
  • 原文地址:https://www.cnblogs.com/ElEGenT/p/13159506.html
Copyright © 2011-2022 走看看