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

时间:2015-07-01 10:40:36

标签: java number-formatting

我有这个功能:

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行是指第二个子字符串是代码段。如果变量f2没有&#34; E&#34;我可以得到这个结果。在其中,但我无法提供任何可以这样做的输入。

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

4 个答案:

答案 0 :(得分:2)

在我的单元测试中,

失败了
toChar(Double.NaN);
toChar(Double.POSITIVE_INFINITY);
toChar(Double.NEGATIVE_INFINITY);

这些的字符串表示是

NaN
Infinity
-Infinity

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

检查在方法中放置NaN(非数字 - 如1/0)会发生什么。

答案 3 :(得分:0)

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

toChar(Double.NaN);

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

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