c# variable culture string to invariant culture double

61 views Asked by At

I have found many questions for this topic but I couldn't find one that covers my case.

For a string input, which may be or may not be a real number of unknown culture, how can I try to cast it to a double with CultureInfo.InvariantCulture?

Can this be solved for the special case that the decimal separator may be '.' or ',' by some clever algorithm comparing the parsed values?

private double? tryGetDouble(string input) {
    if (double.TryParse(input, NumberStyles.Number | NumberStyles.AllowExponent, CultureInfo.InvariantCulture, out double result)) {
        // This will work for "1.25", but "1,25" will be converted to 125.
        return result;
    }
    return null;
}

I was thinking something along the lines of, parse the string with both a '.' and a ',' culture and reach a verdict based on the comparison of the parsed number in both cases.

2

There are 2 answers

1
Nate Zaugg On

The culture information cannot, and should not be ignored. It would be impossible to even write a custom formatter to do this. How would it know the difference between "1.000" being 1000 or 1?

My best advice would be to pass the culture code for the value you sent along with the input. Somewhere along the way, someone is running in a particular culture code. From there you should be able to load the appropriate culture and parse the number correctly.

0
NineBerry On

Automatically parsing a non-integer decimal number correctly is hard when the number was not formatted in a fixed format or with a fixed culture but you have different documents using different formats.

You have to think about whether you have certain assumptions you can use to help you.

For example, if you know that numbers will never be specified using thousands or other grouping separators, you can simply first replace all commas with dots, remove potential grouping separators and then parse using dot as decimal separator.

If you know that the number will always contain both a number and grouping separator, you know that the last appearing separator is the decimal separator.

If you know that the number of digits after the decimal separator will always be a fixed number, you can first determine the correct decimal separator by looking at the correct position within the string.

There might be other assumptions you could have. For example if you know that numbers will always be in a certain range (like e.g. numbers will always have a value between 10 and 1000) then you could use that to determine which interpretation is correct.


Another approach would be to use information from the context to guess the culture used to write the numbers. For example, if you know the location of the institution or individual who wrote the text, you could guess the culture used from that information. Or use the language of the text surrounding the potential number to guess the correct culture.

But this approach is really not more than guessing. See last paragraph below. No one stops a human being from choosing a different number format than their location or language would suggest. And there are even cultures like Switzerland where the official number format depends on the setting or other criteria or changed recently.


However, if you have no such assumption that is always true, there is a very high risk of guessing a number incorrectly. This is maybe acceptable if the numbers are checked by a human being first and you only generate default values for a form. But otherwise there is a very high risk of using wrong numbers and thereby causing damage to whoever is using the software and/or their customers.