为什么Double.TryParse()对包含double.MaxValue或double.MinValue的字符串返回false?

时间:2010-12-14 16:51:32

标签: c#

我有静态方法,它接受一个输入字符串,如果字符串代表一个数字,则返回原始输入字符串。如果字符串不表示数字,则处理输入字符串并返回转换后的字符串。我正在编写测试用例。我正在尝试验证包含double.MinValuedouble.MaxValue的输入字符串是否保持不变。我已经阅读了很多论坛,包括StackOverflow,并提出了以下逻辑:

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");
}

问题是Double.TryParse()总是返回false。我用一堆不同的方式调用了TryParse(),但结果总是一样,是假的。

如果我使用decimal.MinValue()int.MinValue()float.MinValue(),则此逻辑有效。

有人可以告诉我为什么我的逻辑不能用于double.MinValue吗?

4 个答案:

答案 0 :(得分:20)

这是因为浮点数的存储和显示方式。当该值变为人类可读的字符串时,该值将四舍五入;对于double.MaxValue,该值恰好被四舍五入,以使其不再适合double

您可以使用往返格式“R”将值转换为始终可以解析回相同值的字符串,因为它会返回额外的精度,直到返回正确的值。此外,在将数字格式化为解析时使用相同的文化,以避免文化差异:

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");
}

输出:

1.7976931348623157E+308
parsed

编辑:

我添加了字符串的输出,并验证解析的值实际上仍然是MaxValue。

答案 1 :(得分:7)

您的逻辑没有任何问题,这只是Double.TryParse API的限制。来自documentation

  

通常,如果传递Double.TryParse方法是通过调用Double.ToString方法创建的字符串,则返回原始的Double值。但是,由于精度损失,值可能不相等。此外,尝试解析MinValue或MaxValue的字符串表示会引发OverflowException,如以下示例所示。

文档似乎取自Parse方法并应用于TryParse,因为TryParse没有抛出。但是,段落后面的示例代码使用了TryParse,并期望MaxValueMinValue

失败

答案 2 :(得分:1)

我对这个问题很感兴趣,发现如果你把E20添加到ToString那么它就可以了。

double.MaxValue.ToString("E20")

有趣的问题。

更新:

我测试d(解析后的double)和double.MaxValue之间的相等性,它们是相等的。

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");

答案 3 :(得分:1)

问题在于舍入ToString()方法。根据文档的实际MaxValue是1.7976931348623157E + 308,但是ToString()会给你1,79769313486232E + 308,它被四舍五入,因此太大而无法解析。

相关问题