无法解释数字格式中的异常

Posted

技术标签:

【中文标题】无法解释数字格式中的异常【英文标题】:Can't explain exception in number formatting 【发布时间】:2015-07-01 10:40:36 【问题描述】:

我有这个功能:

static private DecimalFormat df1 = new DecimalFormat("#0.###############",
        new DecimalFormatSymbols(Locale.US));
static private DecimalFormat df2 = new DecimalFormat(
        "0.0##############E000", new DecimalFormatSymbols(Locale.US));

    public static String toChar(final double val) 
        String cont = Double.toString(val);
        final String f1 = df1.format(val);
        final String f2 = df2.format(val);
        try 
            final double v1 = df1.parse(f1).doubleValue();
            final double v2 = df2.parse(f2).doubleValue();
            if (Math.abs(v1 - val) <= Math.abs(v2 - val) && f1.length() < 16) 
                // 6.0 -> 6
                cont = f1;
             else 
                final int j = f2.indexOf('E');
                if (f2.charAt(j + 1) == '-') 
                    cont = f2.substring(0, j - 1) + "e" + f2.substring(j + 1);
                 else 
                    cont = f2.substring(0, j - 1) + "e+" + f2.substring(j + 1);
                
            
         catch (final ParseException e) 
            throw new AssertionError(e);
        
        return cont;
    

现在,奇怪的事实是我们的一个客户能够从这段代码中获得异常:

java.lang.StringIndexOutOfBoundsException: String index out of range: -2
Begin trace of call stack:
Level  0:    String.substring(..) java.lang.String.java, -1
Level  1:    Functions.toChar(..) ....runtime.Functions.java, 1579
...

第1579行是指第二个子串是代码sn-p。如果变量f2 中没有“E”,我可以得到这个结果,但我无法提供任何可以这样做的输入。

你们有没有看到我们在这里忽略的问题?

【问题讨论】:

【参考方案1】:

在我的单元测试中它失败了

toChar(Double.NaN);
toChar(Double.POSITIVE_INFINITY);
toChar(Double.NEGATIVE_INFINITY);

那些的字符串表示是

NaN
Infinity
-Infinity

【讨论】:

【参考方案2】:

由于您没有提供实际导致此错误发生的双精度值,我们只能猜测:

f2 没有'E' 所以indexOf 返回-1,因此j - 1 = -2,这是substring() 的无效索引。你应该检查indexOf的返回值。

【讨论】:

我不知道是什么数字导致错误,但 Double.NaN 可能是一个不错的猜测... @Thorsten 调试和/或日志记录是你的朋友。【参考方案3】:

当你像这样传递Double.NaN 时会发生这种情况:

toChar(Double.NaN);

(可能是产生相同的其他值和范围),因此只需:

public static String toChar(final double val) 
    if(Double.isNaN(val)) 
        return "NaN";
    
    ...

【讨论】:

@Thorsten 为什么你选择这个答案作为正确的答案,而在这个答案真正逃脱我之前,其他答案已经说过了......【参考方案4】:

检查如果在方法中输入 NaN(不是数字 - 像 1/0)会发生什么。

【讨论】:

以上是关于无法解释数字格式中的异常的主要内容,如果未能解决你的问题,请参考以下文章

java中的数字格式异常,输入错误

java中的数字格式异常[重复]

双无效。 android中的数字格式异常

从字符串到整数的转换中的Java数字格式异常[重复]

使用 DecimalFormat 进行格式化会引发异常 - “无法将给定对象格式化为数字”

令人困惑的数字格式异常