Java DecimalFormat 在执行指数符号时会产生错误
Posted
技术标签:
【中文标题】Java DecimalFormat 在执行指数符号时会产生错误【英文标题】:Java DecimalFormat creates error when enforcing exponent sign 【发布时间】: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)我感谢任何见解。 谢谢, 标记
【问题讨论】:
重新格式化的代码;如果不正确,请恢复。 【参考方案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 的一个特性。请务必在您的代码中记录潜在的本地化问题。以上是关于Java DecimalFormat 在执行指数符号时会产生错误的主要内容,如果未能解决你的问题,请参考以下文章