OverFlowException없이 "1.79769313486232E+308"을 두 배로 변환 하시겠습니까?

StackOverflow https://stackoverflow.com/questions/766918

  •  12-09-2019
  •  | 
  •  

문제

이 문자열이 "1.79769313486232E+308"을 가지고 있으며 .NET 숫자 값 (Double?)으로 변환하려고하지만 아래 예외를 얻고 있습니다. 나는 사용 중입니다 Convert.ToDouble(). 이 변환을 수행하는 올바른 방법은 무엇입니까?

OverflowException : 값은 두 배에 비해 너무 크거나 작았습니다.

도움이 되었습니까?

해결책

문제는 그 사실 때문일 수 있습니다 Double.MaxValue 문자열로 변환되었고 문자열이 출력되면 모든 숫자가 출력되지 않고 대신 둥글게됩니다. 이 값을 구문 분석하면 두 배가 넘쳐납니다.

사용 Double.TryParse 그리고 그 후 실패 및 대체의 경우 "1.79769313486232E+308"문자열에서 평등을 확인합니다. Double.MaxValue 문자열을 그대로 유지 해야하는 경우 빠른 해결 방법이어야합니다.

편집 : 물론 문자열을 그대로 유지할 필요가 없다면 사용하십시오. 왕복 형식 지정자 처음에 문자열을 생성하려면 존은 그의 대답에 대해 설명합니다.

다른 팁

불행히도이 값은보다 큽니다 double.MaxValue, 따라서 예외입니다.

Codekaizen이 제안한 것처럼 문자열 테스트를 하드 코딩 할 수 있습니다. 당신이 하나라면 더 나은 (imo) 대안 생산 먼저 문자열은 "r"형식 지정자를 사용하는 것입니다. 그런 다음 생성 된 문자열은 "1.7976931348623157E+308"대신에 올바르게 파싱됩니다.

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

분명히 데이터를 제어 할 수 없다면 도움이되지는 않지만이 경우 이미 데이터를 잃어 버릴 것임을 이해해야합니다.

당신은 시도 할 수 있습니다 double.Parse() 또는 double.TryParse() 보다는 Convert.ToDouble(), 그러나 나는 당신이 더 나은 결과를 얻을 것이라고 확신하지 못한다. 또한, 당신이 제공하는 문자열은 double.MaxValue, 이것은 물론 두 배로 포함 할 수있는 최대 값이므로 오류가 발생하는 곳 일 가능성이 높습니다. 플로팅 포인트 숫자 유형은 까다 롭기 때문에 어떤 종류의 반올림이 일어나고 있으며 유형의 한계 밖으로 밀고 있다고 가정합니다.

당신은 또한 시도 할 수 있습니다 decimal 데이터 형식. 당신은 거기에서 더 좋은 행운을 가지고있을 것입니다.

여기 내가 생각해 낸 것입니다. 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;
}

문제와 해결책을 보여줍니다.

var s = double.MaxValue.ToString();
double d;
if (!double.TryParse(s, out d)) {
    d = s.Equals(double.MaxValue) ? double.MaxValue : double.MinValue;
}

여기서는 서로 다른 형식과 배양을 나타내는보다 일반적인 구현이 더 관대합니다.

#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;
}

예외가 말한 것처럼 그 숫자는 더블에 비해 너무 큽니다. .NET 라이브러리에 매우 많은 숫자를 처리하는 것이 없기 때문에 당신은 당신을 위해 그것을 처리하기 위해 많은 숫자 라이브러리를 찾아야 할 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top