Double.TryParse thousand separator returns unexpected result
Asked Answered
V

3

8

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.

Vitriolic answered 6/9, 2012 at 12:31 Comment(10)
why aren't you passing the IFormatProvider?Redcoat
For the record, I am getting correct results in all three calls. What is your CurrentCulture?Blackington
What does Double.TryParse return in this case? True or false? Cause if parsing fails result is set to 0George
I am also getting a correct parse in all three cases after setting Thread.Current.CurrentCulture = new CultureInfo("en-us").Skuld
@Rotem: From MSDN: "Any Indicates that all styles except AllowHexSpecifier are used. This is a composite number style."Skuld
Normally does NumberStyles.Any include AllowThousandsGeorge
With en-ZA I get an exception for try3. Start you sample with Thread.CurrentThread.CurrentCulture = new CultureInfo("en-ZA"); so that we all talk about the same thing.Poker
I think the problem might be that CultureInfo.GetCultureInfo("en-ZA").NumberFormat.NumberGroupSeparator; returns a white space.Blackington
@Henk These are the results I get, don't know about the OP.Blackington
Apparently the OP had a tweaked en-ZA. Root of the whole problem.Poker
F
4

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); 
Federalism answered 6/9, 2012 at 12:42 Comment(2)
I will give this a go and see what happens. I see you say that it failed whe using Culture Info en-ZA, even though the numberGroupSeparator is ",". Do you possibly know why?Vitriolic
@astander, I am not sure, I am searching about it, if I find something , will let you knowFederalism
S
4

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)!

Skuld answered 6/9, 2012 at 13:3 Comment(2)
@astander: Turns out I was initially wrong, but I did finally hit upon the correct answer. Please take a look at the edit.Skuld
This is absolutely fantastic. Thank you for the explenation.Vitriolic
C
1

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.

Critter answered 6/9, 2012 at 12:38 Comment(3)
i think, its because of the formatProvider is NULL. I don't see that it is allowed to be nulled ( only in byte: msdn.microsoft.com/de-de/library/tkktxbeh.aspx it is listed as nullable/defaulting)Wept
@Wept - "If provider is null or a NumberFormatInfo object cannot be obtained, the format information for the current culture is used."Blackington
The exceptions from Parse are equally (un)helpful.Poker

© 2022 - 2024 — McMap. All rights reserved.