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(\"
You can't change the internal representation of double
/Double
that way.
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()
.
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
.
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
.
DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance();
symbols.setDecimalSeparator('.');
DecimalFormat format = new DecimalFormat("#.#####", symbols);
value = format.parse(format.format(41251.50000000012343));
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.
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.
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));
The real solution is: don't use floating-point numbers for anything that needs to be counted with precision:
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.