Java DecimalFormat和Double.valueOf()格式
我试图在我的双精度值的小数分隔符之后去掉不必要的符号。我是这样做的:Java DecimalFormat和Double.valueOf()格式,java,number-formatting,decimalformat,Java,Number Formatting,Decimalformat,我试图在我的双精度值的小数分隔符之后去掉不必要的符号。我是这样做的: DecimalFormat format = new DecimalFormat("#.#####"); value = Double.valueOf(format.format(41251.50000000012343)); 但当我运行此代码时,它抛出: java.lang.NumberFormatException: For input string: "41251,5" at sun.misc.Floating
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
类的默认十进制分隔符值?还有其他想法吗?您不能以这种方式更改double
/double
的内部表示形式
如果要更改(人类)表示,只需保留它String
。因此,将该Double#valueOf()
放在一边,并在演示文稿中使用DecimalFormat()的字符串
结果。如果您想使用它进行计算,您可以使用DecimalFormat
和Double\valueOf()
将其转换回实数Double
顺便说一句,根据你的抱怨,我正试图在我的双精度值的十进制分隔符之后去掉不必要的符号?闻起来有点像您在表示层中使用了未格式化的Double,您没有意识到,在普通UI中,您可以使用DecimalFormat
来表示它们,而无需转换回Double
使用Locale.getDefault()
获取系统的十进制分隔符,您也可以设置它。您不能同时使用两个不同的分隔符,因为另一个分隔符通常用作数千的分隔符:2.001.000,23 2001000.23
对于“,
”而不是“
”,您必须更改区域设置
对于小数位数,请使用setMaximumFractionDigits(int newValue)
对于其余部分,.格式化字符串使用
作为十进制分隔符,而异常则抱怨,
指向区域设置问题;i、 e.DecimalFormat正在使用与Double.valueOf不同的区域设置来格式化数字
通常,您应该基于特定的区域设置构造一个NumberFormat
Locale myLocale = ...;
NumberFormat f = NumberFormat.getInstance(myLocale);
从以下的JavaDocs:
要获取特定区域设置(包括默认区域设置)的NumberFormat,请调用NumberFormat的工厂方法之一,例如getInstance()。通常,不要直接调用DecimalFormat构造函数,因为NumberFormat工厂方法可能返回DecimalFormat以外的子类
然而,试图将double格式化为字符串,然后将字符串解析回double是一种非常糟糕的代码味道。我怀疑您所处理的问题是,您希望使用固定精度的十进制数(如货币金额),但由于double是一个浮点数,这意味着许多值(如0.1
)无法精确地表示为double/float,因此遇到了问题。如果是这种情况,处理固定精度十进制数的正确方法是使用。By
在我的双精度值的小数分隔符后去掉不必要的符号
你的意思是要四舍五入到小数点后五位吗?那就用
value = Math.round(value*1e5)/1e5;
(当然,如果你真的想剪掉其他数字,你也可以Math.floor(value*1e5)/1e5
)
编辑
使用此方法(或任何浮点舍入)时要非常小心。对于265.335这样简单的东西,它失败了。中间结果265.335*100(2位精度)为26533.49999996。这意味着它将四舍五入到265.33。从浮点数转换为十进制实数时,存在一些固有的问题。见EJP的答案,见-
问题是十进制格式将值转换为本地化字符串。我猜您的区域设置的默认十进制分隔符是带有“,
”的。这种情况经常发生在法国或世界其他地区
基本上,您需要做的是使用“.”分隔符创建格式化日期,以便Double.valueOf
可以读取它。如注释所示,您也可以使用相同的格式来解析值,而不是使用Double.valueOf
DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance();
symbols.setDecimalSeparator('.');
DecimalFormat format = new DecimalFormat("#.#####", symbols);
value = format.parse(format.format(41251.50000000012343));
与此相关,但不是问题的答案:尝试切换到BigDecimal而不是Double和Float。我在比较这些类型时遇到了很多问题,现在我可以使用BigDecimal了。看起来您的本地语言使用逗号“,”作为十进制分隔符。要将“.”作为十进制分隔符,您必须声明:
DecimalFormat dFormat =new DecimalFormat("#.#", new DecimalFormatSymbols(Locale.ENGLISH));
真正的解决方案是:对于需要精确计数的任何东西,都不要使用浮点数:
- 如果你在处理货币问题,不要使用两倍的美元,使用整数的美分李>
- 如果您处理的是小时数,并且需要计算四分之一小时和10分钟间隔,请使用整数分钟数
浮点数几乎总是某个实数的近似值。它们适用于物理量(最高精度)的测量和计算以及统计伪影
游手好闲地将浮点四舍五入到多个数字是一种代码味道:这是浪费,而且您永远无法真正确定您的代码在所有情况下都能正常工作。我的代码功能:
private static double arrondi(double number){
DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance();
symbols.setDecimalSeparator('.');
DecimalFormat format = new DecimalFormat("#.#####", symbols);
return Double.valueOf(format.format(number));
}
问题是,当我将其转换为字符串时,它将不会使用Double.valueOf()
,将其转换回Double
,因为DecimalFormat
放置,
,其中valueOf()
应为。那么有没有一种方法可以在DecimalFormat
类中重写它(这样我就不必在那里调用replaceAll(“,”,“)
)