Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Double.TryParse thousand separator returns unexpected result

I just ran into something very strange, and was just wondering if I was missing something.

I was trying to parse a string (with thousand separators) into a double, and found the below issue.

CultureInfo ci = CultureInfo.CurrentCulture; // en-ZA
string numberGroupSeparator = CultureInfo.CurrentCulture.NumberFormat.NumberGroupSeparator; //numberGroupSeparator = ,
string numberDecimalSeparator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;//numberDecimalSeparator = .
string strValue = "242,445.24";
double try1;
double try2;
bool btry1 = Double.TryParse(strValue, out try1); //try1 = 242445.24 : btry1 = true
bool btry2 = Double.TryParse(strValue, NumberStyles.Any, null, out try2); //try2 = 0.0 : btry2 = false <- STRANGE
double try3 = Convert.ToDouble(strValue); //try3 = 242445.24

Now the reason why I didnt just want to use Convert.ToDouble is due to scientific notation which has given me some problems before.

Does anybody know why this might be?

EDIT:

I have update my current culture info.

like image 366
Adriaan Stander Avatar asked Sep 06 '12 12:09

Adriaan Stander


3 Answers

Its working on my machine as expected, so I believe it has to do with the Current Culture. Try using CultureInfo.InvariantCulture instead of null in your TryParse

Double.TryParse(strValue, NumberStyles.Any,CultureInfo.InvariantCulture, out try2);

It is failing for your current specified culture en-ZA, I tried the following code and try2 is holding 0.0

 Double.TryParse(strValue, NumberStyles.Any,new CultureInfo("en-ZA"), out try2); 
like image 116
Habib Avatar answered Nov 17 '22 13:11

Habib


Updated (correct) answer, after much digging

You say that your current culture is en-ZA, but checking

new System.Globalization.CultureInfo("en-ZA").NumberFormat.NumberGroupSeparator

we see that the value is the empty string and not "," as the question states. So if we set CultureInfo.CurrentCulture to new CultureInfo("en-ZA") then parsing fails even for try1.

After manually setting it to "," with

Thread.CurrentThread.CurrentCulture.NumberFormat.NumberGroupSeparator = ",";

it transpires that parsing into try1 is successful. Parsing into try2 still fails.

For the TryParse overload used in try2 the documentation is pretty clear that the current thread culture is used when the format provider is null, so something else must be going on...

After carefully comparing InvariantCulture.NumberFormat to that of the en-ZA culture, I noticed that the cultures also differ in their currency formats. Trying

Thread.CurrentThread.CurrentCulture.NumberFormat.CurrencyGroupSeparator = ",";
Thread.CurrentThread.CurrentCulture.NumberFormat.CurrencyDecimalSeparator = ".";

hit the jackpot: parsing succeeds! So what's really going on is that when using NumberStyles.All, the parse treats the number as currency.

The hypothesis can be verified if you try

double.TryParse(strValue,
                NumberStyles.Any & ~NumberStyles.AllowCurrencySymbol, null, out try2);

which succeeds without needing to mess with the currency separators (of course the NumberGroupSeparator does have to be appropriate)!

like image 28
Jon Avatar answered Nov 17 '22 15:11

Jon


The documentation says that 0.0 is returned, when the conversation fails.

Most likely TryParse returns false, and you should try calling Parse, to get an exception message that might tell you what is wrong.

like image 1
Wutz Avatar answered Nov 17 '22 15:11

Wutz