Don
Don

Reputation: 789

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

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?

Upvotes: 17

Views: 7992

Answers (4)

Guffa
Guffa

Reputation: 700362

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.

Upvotes: 22

phillip
phillip

Reputation: 2738

I got interested in this question and found that if you add E20 to ToString then it works.

double.MaxValue.ToString("E20")

Interesting question though.

UPDATE:

I test equality between d (the parsed double) and double.MaxValue and they are equal.

var abc = Double.Parse(double.MaxValue.ToString("E20"));
abc.Dump();

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

if(d == double.MaxValue) Console.WriteLine("parsed value is equal to MaxValue");
else Console.WriteLine("parsed value is NOT equal to MaxValue");

Upvotes: 1

TToni
TToni

Reputation: 9391

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.

Upvotes: 1

JaredPar
JaredPar

Reputation: 754763

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

Upvotes: 7

Related Questions