DecimalFormat和Double.valueOf()

时间:2010-04-22 13:09:30

标签: java number-formatting decimalformat

我试图在我的double值的十进制分隔符后删除不必要的符号。我是这样做的:

DecimalFormat format = new DecimalFormat("#.#####");
value = Double.valueOf(format.format(41251.50000000012343));

但是,当我运行此代码时,它会抛出:

java.lang.NumberFormatException: For input string: "41251,5"
    at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1224)
    at java.lang.Double.valueOf(Double.java:447)
    at ...

正如我所见,Double.valueOf()适用于"11.1"之类的字符串,但它会像"11,1"这样的字符串窒息。我该如何解决这个问题?是否有更优雅的方式,然后像

Double.valueOf(format.format(41251.50000000012343).replaceAll(",", "."));

有没有办法覆盖DecimalFormat类的默认小数点分隔符值?还有其他想法吗?

10 个答案:

答案 0 :(得分:76)

通过

  

在我的双值的小数分隔符后删除不必要的符号

你真的是说你想要绕到例如小数点后五位?然后使用

value = Math.round(value*1e5)/1e5;

(当然,如果你真的希望其他数字被切断,你也可以Math.floor(value*1e5)/1e5

答案 1 :(得分:25)

问题是您的十进制格式会将您的值转换为本地化字符串。我猜你的语言环境的默认小数点分隔符是','。这通常发生在法国语言环境或世界其他地方。

基本上您需要做的是使用'。'创建格式化日期。分隔符Double.valueOf可以读取它。如注释所示,您可以使用相同的格式来解析值,而不是使用Double.valueOf

DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance();
symbols.setDecimalSeparator('.');
DecimalFormat format = new DecimalFormat("#.#####", symbols);
value = format.parse(format.format(41251.50000000012343));

答案 2 :(得分:5)

您的格式化字符串使用.作为小数点分隔符,而异常抱怨,指向Locale问题;即DecimalFormat使用不同的Locale格式化数字,而不是Double.valueOf期望的格式。

通常,您应该根据特定的区域设置构建NumberFormat

Locale myLocale = ...;
NumberFormat f = NumberFormat.getInstance(myLocale);

来自DecimalFormat的JavaDocs:

  

要获取特定区域设置的NumberFormat(包括默认区域设置),请调用NumberFormat的工厂方法之一,例如getInstance()。通常,不要直接调用DecimalFormat构造函数,因为NumberFormat工厂方法可能返回除DecimalFormat之外的子类。

然而as BalusC points out,尝试将double格式化为String然后将String解析回double是一个非常糟糕的代码味道。我怀疑你正在处理你期望固定精度十进制数(例如货币金额)但是遇到问题的问题,因为double是浮点数,这意味着许多值(例如{{1} })不能精确表示为double / float。如果是这种情况,处理固定精度十进制数的正确方法是使用BigDecimal

答案 3 :(得分:4)

使用Locale.getDefault()获取系统的小数分隔符,您也可以设置它。您不能同时使用不同的分隔符,因为另一个分隔符通常用作数千个分隔符:2.001.000,23< => 2,001,000.23

答案 4 :(得分:3)

看起来像你的本地使用逗号“,”作为小数分隔。得到“。”作为小数点分隔符,您必须声明:

DecimalFormat dFormat =new DecimalFormat("#.#", new DecimalFormatSymbols(Locale.ENGLISH));

答案 5 :(得分:2)

您不能以这种方式更改double / Double的内部表示。

如果您想要更改(人类)表示,请保持String。因此,请离开Double#valueOf()并在演示文稿中使用String的{​​{1}}结果。如果您想要使用它进行计算,您始终可以使用DecimalFormat#format()Double转换回真实DecimalFormat

顺便说一下,根据你的抱怨我试图在我的双重值的小数分隔符后删除不必要的符号are you aware of the internals of floating point numbers?它有点像你在表示层中使用未格式化的双打,并且你没有意识到使用普通用户界面你可以使用Double#valueOf()呈现它们而无需转换回{{1} }。

答案 6 :(得分:2)

对于“,”而不是“.”,您必须更改区域设置。

对于小数位数,请使用setMaximumFractionDigits(int newValue)

其余的see the javadoc

答案 7 :(得分:2)

与此有些相关,但不是问题的答案:尝试切换到BigDecimal而不是double和float。我对这些类型的比较存在很多问题,现在我很高兴使用BigDecimal。

答案 8 :(得分:2)

真正的解决方案是:不要将浮点数用于需要精确计算的任何事物:

  • 如果您正在处理货币,请不要使用双倍数的美元,使用整数美分。
  • 如果您要处理数小时的时间并且需要计算四分之一小时和10分钟的间隔,请使用整数分钟。

浮点数几乎总是某个实际值的近似值。它们适用于物理量的测量和计算(最高精度)和统计工件。

将浮点数舍入为多个数字而愚弄代码气味:它很浪费,您无法确定代码在所有情况下都能正常工作。

答案 9 :(得分:0)

我的代码功能:

 private static double arrondi(double number){
         DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance();
         symbols.setDecimalSeparator('.');
         DecimalFormat format = new DecimalFormat("#.#####", symbols);
         return Double.valueOf(format.format(number));
     }