Java DecimalFormat 和 Double.valueOf()
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2691018/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
DecimalFormat and Double.valueOf()
提问by folone
I'm trying to get rid of unnecessary symbols after decimal seperator of my double value. I'm doing it this way:
我试图在我的双精度值的十进制分隔符之后去掉不必要的符号。我是这样做的:
DecimalFormat format = new DecimalFormat("#.#####");
value = Double.valueOf(format.format(41251.50000000012343));
But when I run this code, it throws:
但是当我运行这段代码时,它抛出:
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 ...
As I see, Double.valueOf()
works great with strings like "11.1"
, but it chokes on strings like "11,1"
. How do I work around this? Is there a more elegant way then something like
依我之见,Double.valueOf()
伟大工程与像琴弦"11.1"
,但它扼流圈像串"11,1"
。我该如何解决这个问题?有没有更优雅的方式然后像
Double.valueOf(format.format(41251.50000000012343).replaceAll(",", "."));
Is there a way to override the default decimal separator value of DecimalFormat
class? Any other thoughts?
有没有办法覆盖类的默认十进制分隔符值DecimalFormat
?还有其他想法吗?
采纳答案by Tobias Kienzler
By
经过
get rid of unnecessary symbols after decimal seperator of my double value
在我的 double 值的十进制分隔符之后去掉不必要的符号
do you actually mean you want to round to e.g. the 5th decimal? Then just use
你真的是说你想四舍五入到小数点后第五位吗?然后只需使用
value = Math.round(value*1e5)/1e5;
(of course you can also Math.floor(value*1e5)/1e5
if you really want the other digits cut off)
(当然,Math.floor(value*1e5)/1e5
如果你真的想切断其他数字,你也可以)
回答by BalusC
You can't change the internal representation of double
/Double
that way.
您不能以这种方式更改double
/的内部表示Double
。
If you want to change the (human) representation, just keep it String
. Thus, leave that Double#valueOf()
away and use the String
outcome of DecimalFormat#format()
in your presentation. If you ever want to do calculations with it, you can always convert back to a real Double
using DecimalFormat
and Double#valueOf()
.
如果您想更改(人类)表示,只需保留它String
。因此,把它Double#valueOf()
放在String
一边,DecimalFormat#format()
在你的演示文稿中使用结果。如果您想用它进行计算,您可以随时Double
使用DecimalFormat
and转换回真正的Double#valueOf()
。
By the way, as per your complain I'm trying to get rid of unnecessary symbols after decimal seperator of my double value, are you aware of the internals of floating point numbers? It smells a bit like that you're using unformatted doubles in the presentation layer and that you didn't realize that with the average UI you can just present them using DecimalFormat
without the need to convert back to Double
.
顺便说一句,根据你的抱怨,我试图在我的双精度值的十进制分隔符之后去掉不必要的符号,你知道浮点数的内部结构吗?闻起来有点像您在表示层中使用了未格式化的双精度,并且您没有意识到使用一般的 UI,您可以直接使用它们来呈现它们,DecimalFormat
而无需将它们转换回Double
.
回答by Tobias Kienzler
Use Locale.getDefault()
to get your System's decimal separator which you can also set. You can't have to different separators at the same time since the other is then usually used as seprator for thousands: 2.001.000,23 <=> 2,001,000.23
使用Locale.getDefault()
让您的系统的小数点分隔符,你也可以设置。您不能同时使用不同的分隔符,因为另一个通常用作数千个分隔符:2.001.000,23 <=> 2,001,000.23
回答by Maxime ARNSTAMM
For the ',
' instead of the '.
' , you'd have to change the locale.
对于 ' ,
' 而不是 ' .
' ,您必须更改语言环境。
For the number of decimals, use setMaximumFractionDigits(int newValue)
.
对于小数位数,使用setMaximumFractionDigits(int newValue)
.
For the rest, see the javadoc.
其余的,请参阅 javadoc。
回答by matt b
The fact that your formatting string uses .
as the decimal separator while the exception complains of ,
points to a Locale issue; i.e. DecimalFormat is using a different Locale to format the number than Double.valueOf expects.
您的格式化字符串.
用作小数点分隔符而异常抱怨,
指向区域设置问题的事实;即 DecimalFormat 使用不同的区域设置来格式化数字,而不是 Double.valueOf 预期的。
In general, you should construct a NumberFormat
based on a specific Locale.
通常,您应该NumberFormat
基于特定的 Locale构建一个。
Locale myLocale = ...;
NumberFormat f = NumberFormat.getInstance(myLocale);
From the JavaDocs of DecimalFormat:
来自DecimalFormat的 JavaDocs :
To obtain a NumberFormat for a specific locale, including the default locale, call one of NumberFormat's factory methods, such as getInstance(). In general, do not call the DecimalFormat constructors directly, since the NumberFormat factory methods may return subclasses other than DecimalFormat.
要获取特定语言环境(包括默认语言环境)的 NumberFormat,请调用 NumberFormat 的工厂方法之一,例如 getInstance()。通常,不要直接调用 DecimalFormat 构造函数,因为 NumberFormat 工厂方法可能返回 DecimalFormat 以外的子类。
However as BalusC points out, attempting to format a double as a String and then parse the String back to the double is a pretty bad code smell. I would suspect that you are dealing with issues where you expect a fixed-precision decimal number (such as a monetary amount) but are running into issues because double is a floating point number, which means that many values (such as 0.1
) cannot be expressed precisely as a double/float. If this is the case, the correct way to handle a fixed-precision decimal number is to use a BigDecimal
.
然而,正如 BalusC 指出的那样,尝试将 double 格式化为 String 然后将 String 解析回 double 是一种非常糟糕的代码味道。我怀疑您正在处理您期望固定精度十进制数(例如货币金额)但遇到问题的问题,因为 double 是浮点数,这意味着许多值(例如0.1
)无法表示精确地作为双/浮点数。如果是这种情况,处理固定精度十进制数的正确方法是使用BigDecimal
.
回答by Chris Dail
The problem is that your decimal format converts your value to a localized string. I'm guessing that your default decimal separator for your locale is with a ',
'. This often happens with French locales or other parts of the world.
问题是您的十进制格式将您的值转换为本地化字符串。我猜您的语言环境的默认小数点分隔符带有“ ,
”。这通常发生在法国地区或世界其他地区。
Basically what you need to do is create your formatted date with the '.' separator so Double.valueOf
can read it. As indicated by the comments, you can use the same format to parse the value as well instead of using Double.valueOf
.
基本上你需要做的是用“.”创建格式化日期。分隔符所以Double.valueOf
可以阅读它。如注释所示,您也可以使用相同的格式来解析值,而不是使用Double.valueOf
.
DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance();
symbols.setDecimalSeparator('.');
DecimalFormat format = new DecimalFormat("#.#####", symbols);
value = format.parse(format.format(41251.50000000012343));
回答by Joao Coelho
Somewhat related to this, but not an answer to the question: try switching to BigDecimal instead of doubles and floats. I was having a lot of issue with comparisons on those types and now I'm good to go with BigDecimal.
与此有些相关,但不是问题的答案:尝试切换到 BigDecimal 而不是双精度数和浮点数。我在比较这些类型时遇到了很多问题,现在我很高兴使用 BigDecimal。
回答by Vaibhav Barad
looks like your local use a comma "," as a decimal separation.To get the "." as a decimal separator, you will have to declare:
看起来你的本地使用逗号“,”作为小数分隔。要得到“。” 作为小数分隔符,您必须声明:
DecimalFormat dFormat =new DecimalFormat("#.#", new DecimalFormatSymbols(Locale.ENGLISH));
回答by PaulMurrayCbr
The real solution is: don't use floating-point numbers for anything that needs to be counted with precision:
真正的解决方案是:不要对任何需要精确计数的东西使用浮点数:
- If you are dealing with currency, don't use a double number of dollars, use an integer number of cents.
- If you are dealing with hours of time and need to count quarter-hours and 10-minute intervals, use an integer number of minutes.
- 如果您处理货币,请不要使用双倍数的美元,而使用整数美分。
- 如果您要处理几小时的时间并且需要计算四分之一小时和 10 分钟的间隔,请使用整数分钟。
A floating point number is almost always an approximation of some real value. They are suitable for measurements and calculation of physical quantities (top a degree of precision) and for statistical artifacts.
浮点数几乎总是某个实数值的近似值。它们适用于物理量的测量和计算(最高精确度)和统计工件。
Fooling about with rounding floating point to a number of digits is a code smell: it's wasteful and you can never really be sure that your code will work properly in all cases.
将浮点数四舍五入为多个数字是一种代码味道:这是一种浪费,您永远无法真正确定您的代码在所有情况下都能正常工作。
回答by Neoray
My code function :
我的代码功能:
private static double arrondi(double number){
DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance();
symbols.setDecimalSeparator('.');
DecimalFormat format = new DecimalFormat("#.#####", symbols);
return Double.valueOf(format.format(number));
}