15

我有这个字符串“1.79769313486232E+308”并试图将其转换为 .NET 数值(双精度值?),但出现以下异常。我正在使用Convert.ToDouble(). 进行这种转换的正确方法是什么?

溢出异常:对于 Double 而言,值太大或太小

4

8 回答 8

26

不幸的是,这个值大于double.MaxValue,因此例外。

正如 codekaizen 建议的那样,您可以对字符串的测试进行硬编码。如果您是首先生成字符串的人,那么更好的(IMO)替代方法是使用“r”格式说明符。然后您生成的字符串将改为“1.7976931348623157E+308”,然后正确解析:

string s = double.MaxValue.ToString("r");
double d = double.Parse(s); // No exception

显然,如果您无法控制数据,那将无济于事——但您应该明白,在这种情况下,您可能已经丢失了数据。

于 2009-04-20T05:28:28.087 回答
15

问题可能是由于Double.MaxValue转换为字符串,输出字符串时,并不是所有的数字都输出,而是四舍五入。解析这个值会溢出双精度值。

在失败的情况下使用Double.TryParse并随后检查字符串“1.79769313486232E+308”的相等性Double.MaxValue,如果您需要保持字符串原样,则替换应该是一种快速的解决方法。

编辑:当然,如果您不需要将字符串保持原样,请使用Round Trip 格式说明符首先生成字符串,正如Jon 在他的回答中所描述的那样

于 2009-04-20T05:25:37.110 回答
1

您可以尝试double.Parse()ordouble.TryParse()而不是Convert.ToDouble(),但我不确定您会得到更好的结果。顺便说一句,您提供的字符串等于double.MaxValue,这(当然)是双精度中可以包含的最大值,因此这很可能是您的错误来自哪里。浮点数字类型很挑剔,所以我假设正在发生某种舍入并将其推到类型的范围之外。

您也可以尝试decimal数据类型。在那里你可能会有更好的运气。

于 2009-04-20T04:51:23.387 回答
1

这是我想出的。感谢 Jon Skeet 和 codekaizen。

private double convertToDouble(string str)
{
    double dbl;

    if (double.TryParse(str, out dbl))
        return dbl;

    if (str == "1.79769313486232E+308")
        return double.MaxValue;

    return double.MinValue;
}
于 2009-04-20T07:29:12.243 回答
0

演示问题和解决方案:

var s = double.MaxValue.ToString();
double d;
if (!double.TryParse(s, out d)) {
    d = s.Equals(double.MaxValue) ? double.MaxValue : double.MinValue;
}
于 2012-05-17T16:28:19.807 回答
0

Here a more generic implementation which representing different formatting and cultures and is more tolerant:

#region MatchDoubleMinMaxValuesRegex
/// <summary>
/// This regex matches strings which represents either a <see cref="double.MinValue"/> or a <see cref="double.MaxValue"/>.
/// If it is a <see cref="double.MinValue"/> then the group "isNegative" will be matched as <see cref="Group.Success"/>.
/// </summary>
private static readonly Regex MatchDoubleMinMaxValuesRegex = new Regex(
    @"
        ^
        (?>(?<isNegative>-)|\+?)
        1
        (?>[,.]?)
        79769313486232
        (?>
            [eE]\+308|
            0{294}(?>[,.]|$)
        )
    ",
    RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace
);
#endregion

/// <summary>
/// Converts the string representation of a number in a specified culture-specific format to its double-precision floating-point number equivalent.
/// <para>This implementation is more tolerant compared to the native double.Parse implementation:
/// strings representing <see cref="double.MinValue"/> and <see cref="double.MaxValue"/> can be parsed without <see cref="OverflowException"/>.</para>
/// </summary>
/// <param name="s">A string that contains a number to convert.</param>
/// <param name="cultureInfo">For some type conversions optional culture information that shall be used to parse the value.
/// If not specified, then the Current Culture will be used.</param>
/// <param name="numberStyles">For some type conversions optional number style configuration that shall be used to parse the value.
/// If not specified, then the default will be used.</param>
/// <returns>A double-precision floating-point number that is equivalent to the numeric value or symbol specified in <paramref name="s"/>.</returns>
/// <exception cref="ArgumentNullException"><paramref name="s"/> is <c>null</c>.</exception>
/// <exception cref="FormatException"><paramref name="s"/> does not represent a number in a valid format.</exception>
/// <exception cref="OverflowException"><paramref name="s"/> represents a number that is less than <see cref="double.MinValue"/> or greater than <see cref="double.MaxValue"/>.</exception>
public static double ParseDoubleEx(string s, CultureInfo cultureInfo = null, NumberStyles? numberStyles = null)
{
    // Try parse
    double tempValue;
    bool parseSuccess = (numberStyles != null)
        ? double.TryParse(s, numberStyles.Value, cultureInfo, out tempValue)
        : double.TryParse(s, NumberStyles.Any, cultureInfo, out tempValue);

    // If parsing failed, check for Min or Max Value (by pattern)
    if (parseSuccess == false)
    {
        Match match = MatchDoubleMinMaxValuesRegex.Match(s);
        if (match.Success == true)
            tempValue = (match.Groups["isNegative"].Success == false)
                ? double.MaxValue
                : double.MinValue;
        else
            throw new OverflowException("A double-precision floating-point number that is equivalent to the numeric value or symbol specified in s.");
    }

    return tempValue;
}
于 2018-05-13T09:12:57.543 回答
-1

我有时会收到相同的号码。这是我如何解决它的。

var str = "1.79769313486232E+308"; var dbl = double.Parse(str.Replace("E+", ""));

于 2020-06-05T14:35:21.620 回答
-2

正如例外所说,这个数字对于双倍来说太大了。您将不得不找到一个大数字库来为您处理这个问题,因为我所知道的 .Net 库中没有任何东西可以处理非常大的数字。

于 2009-04-20T04:53:15.830 回答