DecimalFormat和Double.valueOf()

fol*_*one 12 java number-formatting decimalformat

我想在我的double值的十进制分隔符之后摆脱不必要的符号.我是这样做的:

DecimalFormat format = new DecimalFormat("#.#####");
value = Double.valueOf(format.format(41251.50000000012343));
Run Code Online (Sandbox Code Playgroud)

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

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 ...
Run Code Online (Sandbox Code Playgroud)

正如我所看到的Double.valueOf()那样"11.1",对于字符串很有效,但它会像字符串那样窒息"11,1".我该如何解决这个问题?是否有更优雅的方式

Double.valueOf(format.format(41251.50000000012343).replaceAll(",", "."));
Run Code Online (Sandbox Code Playgroud)

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

Tob*_*ler 78

通过

在我的double值的十进制分隔符后删除不必要的符号

你真的的意思是你想要舍入到例如小数点后五位吗?然后就用吧

value = Math.round(value*1e5)/1e5;
Run Code Online (Sandbox Code Playgroud)

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


Chr*_*ail 24

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

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

DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance();
symbols.setDecimalSeparator('.');
DecimalFormat format = new DecimalFormat("#.#####", symbols);
value = format.parse(format.format(41251.50000000012343));
Run Code Online (Sandbox Code Playgroud)

  • 我很想拒绝这个答案 - 不是因为它没有解决问题,而是因为它支持这种疯狂的四舍五入的尝试 - [OP承认是什么目标](http://stackoverflow.com/questions/ 2691018/DecimalFormat的和 - 双的valueOf/2691162#comment2712294_2691162).但从技术上讲,这是OP要求的答案: - / (7认同)
  • @VipulPurohit对于这个错误,是的,但对于它背后的问题:不!不应该对浮点数使用字符串操作来执行MATHS (7认同)
  • 或者`DecimalFormat格式=新的DecimalFormat("#"+ symbols.getDecimalSeparator +"#####",符号;`不更改小数点分隔符 (3认同)
  • 如果你已经有了DecimalFormat,为什么不用它来解析呢?比试图构建一个DecimalFormat更加健壮,它的格式化输出可以被Double.valueOf()解析 (2认同)

Pau*_*Cbr 7

真正的解决方案是:不要对任何需要精确计数的内容使用浮点数:

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

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

将浮点四舍五入到多个数字是一种代码味道:这是浪费,而且你永远无法真正确定你的代码在所有情况下都能正常工作。


mat*_*t b 6

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

通常,您应该NumberFormat基于特定的Locale 构造一个.

Locale myLocale = ...;
NumberFormat f = NumberFormat.getInstance(myLocale);
Run Code Online (Sandbox Code Playgroud)

来自DecimalFormat的JavaDocs :

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

然而,正如BalusC指出的那样,尝试将double格式化为String然后将String解析为double是一个非常糟糕的代码味道.我怀疑你正在处理你期望固定精度十进制数(例如货币金额)但是遇到问题的问题,因为double是浮点数,这意味着许多值(例如0.1)无法表达正好是双/浮.如果是这种情况,处理固定精度十进制数的正确方法是使用a BigDecimal.


Tob*_*ler 5

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