Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Double.TryParse() return false for a string containing double.MaxValue or double.MinValue?

Tags:

c#

I have static method that takes a string for input and returns the original input string if the string represents a number. If the string does not represent a number the the input string is processed and a transformed string is returned. I'm writing test cases. I'm trying to verify that an input string containing either double.MinValue or double.MaxValue is returned unchanged. I've read through a number of forums, including StackOverflow, and have come up with the following logic:

string doubleMax = double.MaxValue.ToString();
double d;
CultureInfo cultureInfo = new CultureInfo("en-US", true);
if (Double.TryParse(doubleMax, NumberStyles.Any, cultureInfo.NumberFormat, out d))
{
    Console.WriteLine("parsed");
}
else
{
    Console.WriteLine("couldn't parse");
}

Problem is the Double.TryParse() always returns false. I've called TryParse() in a bunch of different ways, but the result is always the same, false.

This logic works if I use decimal.MinValue(), int.MinValue(), or float.MinValue().

Can someone tell me why my logic isn't working for double.MinValue?

like image 758
Don Avatar asked Dec 14 '10 16:12

Don


People also ask

What does the double TryParse do?

TryParse(String, Double) Converts the string representation of a number to its double-precision floating-point number equivalent. A return value indicates whether the conversion succeeded or failed.

What does TryParse do in c#?

TryParse is . NET C# method that allows you to try and parse a string into a specified type. It returns a boolean value indicating whether the conversion was successful or not. If conversion succeeded, the method will return true and the converted value will be assigned to the output parameter.


3 Answers

That's because of the way that floating point numbers are stored and displayed. The value is rounded when it's turned into a human readable string, and for double.MaxValue it happens to be rounded up so that it no longer fits in a double.

You can use the round-trip format "R" to turn a value into a string that always can be parsed back to the same value, as it adds extra precision until the correct value is returned. Also, use the same culture when formatting the number as parsing it, to avoid culture differences:

CultureInfo cultureInfo = new CultureInfo("en-US", true);
string doubleMax = Double.MaxValue.ToString("R", cultureInfo);
Console.WriteLine(doubleMax);
double d;
if (Double.TryParse(doubleMax, NumberStyles.Any, cultureInfo.NumberFormat, out d)) {
  if (d == Double.MaxValue) {
    Console.WriteLine("parsed");
  } else {
    Console.WriteLine("value changed");
  }
} else {
  Console.WriteLine("couldn't parse");
}

Output:

1.7976931348623157E+308
parsed

Edit:

I added output of the string, and verification that the parsed value actually still is MaxValue.

like image 119
Guffa Avatar answered Oct 07 '22 22:10

Guffa


There's nothing wrong with your logic, it's just a limitation i the Double.TryParse API. From the documentation

Ordinarily, if you pass the Double.TryParse method a string that is created by calling the Double.ToString method, the original Double value is returned. However, because of a loss of precision, the values may not be equal. In addition, attempting to parse the string representation of either MinValue or MaxValue throws an OverflowException, as the following example illustrates.

The documentation appears to be taken from the Parse method and applied to TryParse since TryParse does not throw. But the sample code following the pargraph uses TryParse and expects it to fail for MaxValue and MinValue

like image 36
JaredPar Avatar answered Oct 07 '22 21:10

JaredPar


The problem is in the rounding of the ToString() method. The actual MaxValue according to the documentation is 1.7976931348623157E+308, but the ToString() of that gives you 1,79769313486232E+308, which is rounded up and thus too large to parse.

like image 39
TToni Avatar answered Oct 07 '22 23:10

TToni