DecimalFormat and Double.valueOf()

2019-02-01 23:53发布

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(format.format(41251.50000000012343).replaceAll(",", "."));

Is there a way to override the default decimal separator value of DecimalFormat class? Any other thoughts?

10条回答
一夜七次
2楼-- · 2019-02-02 00:00

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));
     }
查看更多
叛逆
3楼-- · 2019-02-02 00:07

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.

In general, you should construct a NumberFormat based on a specific Locale.

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

From the JavaDocs of DecimalFormat:

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.

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.

查看更多
狗以群分
4楼-- · 2019-02-02 00:09

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));
查看更多
再贱就再见
5楼-- · 2019-02-02 00:11

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.

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.

查看更多
The star\"
6楼-- · 2019-02-02 00:12

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

查看更多
该账号已被封号
7楼-- · 2019-02-02 00:12

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.

查看更多
登录 后发表回答