views:

1493

answers:

6

I want to convert some numbers which I got as strings into Doubles, but these numbers are not in US standard locale, but in a different one. How can I do that?

+17  A: 

Try java.text.NumberFormat. From the Javadocs:

To format a number for a different Locale, specify it in the call to getInstance.

NumberFormat nf = NumberFormat.getInstance(Locale.FRENCH);

You can also use a NumberFormat to parse numbers:

myNumber = nf.parse(myString);

parse() returns a Number; so to get a double, you must call myNumber.doubleValue():

    double myNumber = nf.parse(myString).doubleValue();

Note that parse() will never return null, so this cannot cause a NullPointerException. Instead, parse throws a checked ParseException if it fails.

Edit: I originally said that there was another way to convert to double: cast the result to Double and use unboxing. I thought that since a general-purpose instance of NumberFormat was being used (per the Javadocs for getInstance), it would always return a Double. But DJClayworth points out that the Javadocs for parse(String, ParsePosition) (which is called by parse(String)) say that a Long is returned if possible. Therefore, casting the result to Double is unsafe and should not be tried!
Thanks, DJClayworth!

Michael Myers
Add the .doubleValue() method to the answer and I'll accept it.
Daniel
I see nothing to promise that NumberFormat.parse() returns a Double. In fact it appears to say that if the value can be contained in a Long, it returns Long, causing your method 1 to throw a ClassCastExeption.
DJClayworth
Be careful with French, because the FR_fr locale uses a non-breaking space (U+00A0) as the grouping separator. This causes the text to appear the same as if the separator were a "regular" space (U+0020) (e.g., standard keyboard space). The result is a silent failure where a number string that appears to be correctly formatted like "3 141,59" is parsed to 3 instead of 3141.59 . The string must be specified like "3\u00A0141,59" for it to parse correctly. Also, it's good practice to use the method with ParsePosition and check ParsePosition.getIndex() == inputString.length() after parsing.
Phil
+1  A: 

This should be no problem using java.text.DecimalFormat.

__roland__
+3  A: 

You use a NumberFormat. Here is one example, which I think looks correct.

unwind
+1  A: 

Use NumberFormat.getNumberInstance(Locale)

adrian.tarau
A: 

Do you know which locale it is? Then you can use

DecimalFormat format = DecimalFormat.getInstance(theLocale);
format.parse(yourString);

this will even work for scientific notations, strings with percentage signs or strings with currency symbols.

Fortega
DecimalFormat.getInstance is not guaranteed to return a DecimalFormat, actually. You're really calling NumberFormat.getInstance, which is only guaranteed to return a subclass of NumberFormat. From NumberFormat's docs: "If you want even more control over the format or parsing, or want to give your users more control, you can try casting the NumberFormat you get from the factory methods to a DecimalFormat. This will work for the vast majority of locales; just remember to put it in a try block in case you encounter an unusual one."
Michael Myers
You are right indeed. In my code, I actually useDecimalFormat format = (DecimalFormat)DecimalFormat.getInstance(theLocale);I didn't know it doesn't work for all locales...
Fortega
+1  A: 

NumberFormat is the way to go, but you should be aware of its peculiarities which crop up when your data is less than 100% correct.

I found the following usefull:

http://www.ibm.com/developerworks/java/library/j-numberformat/index.html

If your input can be trusted then you don't have to worry about it.

Jasper Floor