Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Number parsing weirdness

Tags:

c#

This line of code:

Console.WriteLine(Convert.ToInt32(“23,23”) + 1);

Throws an exception. This line of code:

Console.WriteLine(Convert.ToDouble(“23,23”) + 1);

Prints 2324.

Does anybody know why this is the case? I wouldn't think that anything good could come of the second conversion.

like image 374
quillbreaker Avatar asked Jan 19 '10 14:01

quillbreaker


4 Answers

From the MSDN documentation of System.Double.Parse:

The s parameter can contain [...] a string of the form:

[ws][sign][integral-digits[,]]integral-digits[.[fractional-digits]][e[sign]exponential-digits][ws]

Here, the comma (,) stands for "[a] culture-specific thousands separator symbol".

To summarize: If your current culture's thousands separator symbol appears anywhere in the string, it is ignored by Double.Parse (which is invoked internally by Convert.ToDouble).


Int32.Parse(string), on the other hand, does not allow thousands separators in the string:

[ws][sign]digits[ws]

which is why your first example throws an exception. You can change this behavior for both Double.Parse and Int32.Parse by using an overload that allows you to specify NumberStyles, as explained by the other answers.

like image 59
Heinzi Avatar answered Oct 14 '22 17:10

Heinzi


The first fails because int.Parse doesn't allow the thousands separator by default. You can change that using NumberStyles:

int d = int.Parse("11,23",
                  NumberStyles.AllowThousands,
                  CultureInfo.InvariantCulture);

Now it works like the double version which does support thousands separators by default. They presumably succeed because "," when treated as a thousands separator by the parser is completely ignored - even though the comma sometimes doesn't make sense as a thousands separator.

Surprisingly, even this works:

double d = double.Parse("1,,1,2,3", CultureInfo.InvariantCulture);

In the above, d is set to the value 1123.0.

like image 20
Mark Byers Avatar answered Oct 14 '22 18:10

Mark Byers


Console.WriteLine(Convert.ToDouble(“23,23”) + 1);

In this case, the comma is being interpreted as your localization's group separator symbol, and is ignored. See http://msdn.microsoft.com/en-us/library/fd84bdyt.aspx.

Console.WriteLine(Convert.ToInt32(“23,23”) + 1);

In this case, you are using Int32.Parse, which doesn't support group separators by default.

The reasoning behind this is that the integer converter has no localization support by default, because localization adds an additional overhead and there is no reason to add it for a parser that doesn't need to interact with any symbols at all. You can, however, force the parser to support localization with some extra arguments:

int.Parse("11,23", NumberStyles.AllowThousands, CultureInfo.InvariantCulture);

Float/double conversion, on the other hand, have to support a decimal separator. In some cultures, this is ",", in others, it can be " " or ".". Since the function must support localization anyway, it would make no sense for it to only support some localization features by default. Otherwise, the implementation would confuse people who expect that since localization is supported for decimal separator, it would support other localization aspects as well.

like image 6
David Pfeffer Avatar answered Oct 14 '22 17:10

David Pfeffer


Commas are ignored in the conversion to double. If you would like commas to generate an error, then you can use the Double.Parse(string, System.Globalization.NumberStyles) method.

like image 1
Jeffrey L Whitledge Avatar answered Oct 14 '22 16:10

Jeffrey L Whitledge