【问题标题】:Java DecimalFormat creates error when enforcing exponent signJava DecimalFormat 在执行指数符号时会产生错误
【发布时间】:2010-08-06 14:36:38
【问题描述】:

在 Java 中,我试图让 DecimalFormat 在指数符号上强制执行符号。当它是积极的我需要一个加号出现。从我所读到的内容来看,这似乎很简单,但对我自己来说,它总是会引发错误。我很欣赏可能有其他方法可以实现我的目标,但我想了解为什么在这种特定方法中会发生错误。

Double result = 123.456;
String sresult;

//This works
NumberFormat formatter = new DecimalFormat("0.00000E00");
        sresult = formatter.format(result); 
        System.out.println(sresult);        //1.23456E02

//This doesn't work
formatter = new DecimalFormat("0.00000E+00"); //Want to enforce the sign to appear
        sresult = formatter.format(result); 
        System.out.println(sresult);        //Expected 1.23456E+02 but error occurs

抛出的错误:

线程“主”java.lang.IllegalArgumentException 中的异常: 畸形指数模式“0.00000E+00” 在 java.text.DecimalFormat.applyPattern(未知来源) 在 java.text.DecimalFormat.(未知来源) 在 deccheck.main(deccheck.java:13)

我感谢任何见解。 谢谢, 标记

【问题讨论】:

  • 重新格式化的代码;如果不正确,请恢复。

标签: java exponent decimalformat


【解决方案1】:

我想通过j flemm 扩展解决方案。 “E”和“-”不是常数,可以设置为DecimalFormatSymbols。因此,替换必须尊重这一点:

public static String hoola(final String s, final DecimalFormatSymbols symbols) {
    String result;
    final String expo = symbols.getExponentSeparator();
    final char minus = symbols.getMinusSign();
    if (!s.contains(expo + minus)) { // don't blast a negative sign
    result = s.replace(expo, expo + '+');
    } else {result=s;}
    return result;
}

/**
 * @param args
 */
public static void main(final String[] args) {
    final DecimalFormat decForm = (DecimalFormat) NumberFormat
            .getInstance(Locale.GERMAN);
    final DecimalFormatSymbols newSymbols = new DecimalFormatSymbols(
            Locale.GERMAN);
    newSymbols.setExponentSeparator("*10^");
    newSymbols.setMinusSign('\u2212');
    decForm.setDecimalFormatSymbols(newSymbols);
    decForm.applyPattern("0.00000E00");
    System.out.println(hoola(decForm.format(1234.567), decForm
            .getDecimalFormatSymbols()));
    System.out.println(hoola(decForm.format(000.00567), decForm
            .getDecimalFormatSymbols()));
}

结果是:

  • 1,23457*10^+03
  • 5,67000*10^-03

【讨论】:

  • 是的,“坏”模式会破坏这段代码。实现所需行为的一种安全方法是实现自己的 NumberFormat 扩展,例如。
  • 我喜欢。不妨也从DecimalFormatSymbols 中拉出hoola(..) 中的+ 符号。
  • @j flemm:我想要,但如果我正确解释 javadocs,+ 是不可更改的。
  • 好点。我也刚注意到。这是有道理的,因为DecimalFormat 不使用+。它可能在其他本地化常量类之一中。
【解决方案2】:

简单的方法:

formatter = new DecimalFormat("0.00000E00"); // Want to enforce the sign to appear
sresult = formatter.format(result);
if (!sresult.contains("E-")) { //don't blast a negative sign
    sresult = sresult.replace("E", "E+");
}
System.out.println(sresult);

为您的示例输出1.23456E+02

但我不相信有办法从DecimalFormat 模式中做到这一点。或者至少 javadoc 没有表明有一个。

编辑:trashgod 提出了一个很好的观点。如果您打算将其本地化到不同的地区,您可能希望从 DecimalFormatSymbols 获得积极和消极的信号。

编辑 2: Andrei 指出E 也是一个本地化变量。展示了我对本地化的了解。

【讨论】:

  • 在本地化的情况下,也应该使用 DecimalFormatSymbols.getExponentSeparator() 中的 E。这样做的问题是,你不能真正直接使用它们,而不检查是否应该在正则表达式中转义它们(你需要额外检查它是否是一个特殊字符)。
  • @Andrei:+1 是的,我也忘记了。
【解决方案3】:

我不认为“+”字符是模式中可接受的字符(在研究了 javadocs 之后)。指数部分 si 的模式描述为:

 Exponent:
         E MinimumExponent
 MinimumExponent:
         0 MinimumExponent(opt)

如果你在那里添加任何东西,它会混淆解析器。 我认为你唯一的选择是给它正常的模式(没有'+'),然后获取字符串并使用正则表达式在那里添加'+'。

sresult = formatter.format(result);
sresult = sresult.replaceAll("E([^\\-]+)", "E+$1");

最好的选择可能是扩展 DecimalFormat 并在覆盖格式方法中执行此操作

【讨论】:

    【解决方案4】:

    @j flemm 的方法很吸引人,因为“负指数使用本地化减号格式化,而不是模式的前缀和后缀。”—DecimalFormat

    【讨论】:

    • 谢谢大家。我感谢所有的cmets。我认为 javadocs 确实提到了使用 + 号的能力,但我对这个链接上提供的信息感到困惑:docjar.com/docs/api/java/text/DecimalFormat.html 我将按照 j flemm 的建议实施简单的方法,因为本地化不应该影响我。跨度>
    • @Mark:它看起来像 Apache Harmony harmony.apache.org 的一个特性。请务必在您的代码中记录潜在的本地化问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-26
    • 2020-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-07
    相关资源
    最近更新 更多