8

I'd like to know if I'm missing something or not... I'm running under the standard Great British culture.

Double result = 0;
if (Double.TryParse("1,2,3", NumberStyles.Any, CultureInfo.CurrentCulture, out result))
{
   Console.WriteLine(result);
}

Expected output would be nothing... "1,2,3" shouldn't parse as a double. However it does. According to the .NET 2.0 MSDN documentation

AllowThousands Indicates that the numeric string can have group separators; for example, separating the hundreds from the thousands. Valid group separator characters are determined by the NumberGroupSeparator and CurrencyGroupSeparator properties of NumberFormatInfo and the number of digits in each group is determined by the NumberGroupSizes and CurrencyGroupSizes properties of NumberFormatInfo.

Allow thousands is included in NumberStyles.Any. The NumberGroupSizes is 3 for my culture. Is this just a bug in the Double.Parse? seems unlikely but I can't spot what I'm doing wrong....

Ian
  • 33,605
  • 26
  • 118
  • 198
  • This might be why I got a valid result when testing [my answer](http://stackoverflow.com/questions/1014535/float-parse-doesnt-work-the-way-i-wanted/1014559#1014559) on a similar question. – ChrisF Jan 16 '12 at 17:28
  • Just curious, but what is the value of result? – Aaron Jan 16 '12 at 17:45
  • I think you'd have to ask Microsoft if its a bug but, I get the same behaviour as you. Can always do `NumberStyles.Any ^ NumberStyles.AllowThousands` but that's not much use if you are expecting legitmate groups of three. – Jodrell Jan 16 '12 at 17:48
  • 1,,,,,2,3 will also parse as 123. It seems that the `CurrencyGroupSeparator` character is completely ignored in parsing. – Magnus Jan 16 '12 at 17:56
  • @BryceAtNetwork23: As Magnus points out, it parses as "123.0". – Ian Jan 17 '12 at 08:51
  • Here i've shared my solution. http://stackoverflow.com/a/41916721/3930528 – user3930528 Jan 29 '17 at 02:33

1 Answers1

6

It just means the input string can contain zero or more instances of NumberFormatInfo.NumberGroupSeparator. This separator can be used to separate groups of numbers of any size; not just thousands. NumberFormatInfo.NumberGroupSeparator and NumberFormatInfo.NumberGroupSizes are used when formatting decimals as strings. Using Reflector it seems like NumberGroupSeparator is only used to determine if the character is a separator, and if it is, it is skipped. NumberGroupSizes is not used at all.

If you want to validate the string, you could do so using RegEx or write a method to do so. Here's one I just hacked together:

string number = "102,000,000.80";
var parts = number.Split(',');
for (int i = 0; i < parts.Length; i++)
{
    var len = parts[i].Length;
    if ((len != 3) && (i == parts.Length - 1) && (parts[i].IndexOf('.') != 3))
    {
        Console.WriteLine("error");
    }
    else
    {
        Console.WriteLine(parts[i]);
    }
}

// Respecting Culture
static Boolean CheckThousands(String value)
{
    String[] parts = value.Split(new string[] { CultureInfo.CurrentCulture.NumberFormat.NumberGroupSeparator }, StringSplitOptions.None);
    foreach (String part in parts)
    {
        int length = part.Length;
        if (CultureInfo.CurrentCulture.NumberFormat.NumberGroupSizes.Contains(length) == false)
        {
            return false;
        }
    }

    return true;
}
Ian
  • 33,605
  • 26
  • 118
  • 198
Ɖiamond ǤeezeƦ
  • 3,223
  • 3
  • 28
  • 40
  • +1, it appears `NumberGroupSizes` is ignored on parsing (internal method is `Number.ParseNumber`). – user7116 Jan 16 '12 at 18:11
  • I'd just started digging in with Reflector but hadn't the time to get that far down as yet. I'm considering using a Regex actually, but I need to be careful and ensure it's all still culture aware. – Ian Jan 17 '12 at 08:50
  • @Ian You could build your Regex expressions based on the information stored in NumberFormatInfo for each culture. – Ɖiamond ǤeezeƦ Jan 17 '12 at 09:16
  • Yes indeed, think that's what I'm going to do :) Just wanted to make other people aware of that fact. – Ian Jan 17 '12 at 09:18
  • I added a culture aware option. Actually though for anyone using this it's a little more complicated. You want to only look at numeric characters (ignore -,£,$ etc) and you want to stop at the decimal point or whatever separator is used in the culture. – Ian Jan 17 '12 at 11:47
  • The culture specific version fails for 12,345 - got me started though, so thanks – stuartd Oct 13 '20 at 16:53