Arno Smulders
Arno Smulders

Reputation: 117

Number with decimal separator incorrectly cast to Double

I'm experiencing weird behavior when converting a number to a double, when using culture information.
When converting "3,3" using the Dutch culture, is handled correctly. If I convert "3,3" using the US culture, it returns 33. I was expecting an error. See my example:

static void Main(string[] args)
{
    CultureInfo cultureDutch = new CultureInfo("nl-NL");
    CultureInfo cultureUS = new CultureInfo("en-US");

    System.Threading.Thread.CurrentThread.CurrentCulture = cultureDutch;
    Console.WriteLine("Input 3,3 --> Expected 3,3");
    Console.WriteLine("Output = " + Convert.ToDouble("3,3", cultureDutch));
    // Actual result --> 3,3

    Console.WriteLine("Input 3,3 --> Expected InvalidCastException");
    Console.WriteLine("Output = " + Convert.ToDouble("3,3", cultureUS));
    // Actual result --> 33

    Console.WriteLine();
    Console.WriteLine();

    System.Threading.Thread.CurrentThread.CurrentCulture = cultureUS;
    Console.WriteLine("Input 3.3 --> Expected InvalidCastException");
    Console.WriteLine("Output = " + Convert.ToDouble("3.3", cultureDutch));
    // Actual result --> 33

    Console.WriteLine("Input 3.3 --> Expected 3.3");
    Console.WriteLine("Output = " + Convert.ToDouble("3.3", cultureUS));
    // Actual result --> 3.3
    Console.ReadLine();
}

What is the correct way to handle this? I would prefer an exception when a decimal (or thousand) separator is invalid.

Upvotes: 7

Views: 283

Answers (2)

Arno Smulders
Arno Smulders

Reputation: 117

Together with the answer from Boas Enkler, I've been able to solve the problem. So first I'll scan the input for thousand separators, based on current culture. And finally I'll parse the input value to a double.

private static string RemoveThousandSeparator(string input)
    {
        Regex removeThousandSeparatorExpr = new Regex(@"^-?(?:\d+|\d{1,3}(?:\"
                        + <CultureInfo>.NumberGroupSeparator + @"\d{3})+)(?:\"
                        + <CultureInfo>.NumberDecimalSeparator + @"\d+)?$");
        Match match = removeThousandSeparatorExpr.Match(input);
        if (match.Success)
        {
            input = input.Replace(<CultureInfo>.NumberGroupSeparator, "");
        }
        else
        {
            throw new Exception("Invalid input value");
        }

        return input;
    }

Upvotes: 0

Boas Enkler
Boas Enkler

Reputation: 12557

If you just want to parse it I would use the dedicated parse methods in which you can set Numberstyles

The following code would throw a FormatException

var culture =new CultureInfo("en-US");
var result = double.Parse("3,3", NumberStyles.AllowDecimalPoint, culture);

For further information see Double.Parse Method

Upvotes: 2

Related Questions