Question

J'ai cette chaîne « 1.79769313486232E + 308 » et essaie de le convertir en une valeur numérique .NET (deux?), Mais je reçois l'exception ci-dessous. J'utilise Convert.ToDouble(). Quelle est la bonne façon de faire cette conversion?

  

OverflowException: valeur était trop grande ou trop petite pour une double

Était-ce utile?

La solution

Le problème est probablement dû au fait que Double.MaxValue a été converti en une chaîne, et quand la chaîne est sortie, tous les chiffres sont sortis, il est plutôt arrondie. Cette valeur Parsing déborde le double.

Utilisation Double.TryParse et vérifier ensuite l'égalité sur la chaîne « 1.79769313486232E + 308 » en cas d'échec et Double.MaxValue substitution devrait être une solution rapide, si vous avez besoin de garder la chaîne la façon dont il est.

EDIT: Bien sûr, si vous n'avez pas besoin de garder la chaîne la façon dont il est, utilisez le Round spécificateur format de voyage pour produire la chaîne en premier lieu, comme Jon décrit dans sa réponse .

Autres conseils

Malheureusement, cette valeur est supérieure à double.MaxValue, donc l'exception.

Comme codekaizen suggère, vous pourriez coder en dur un test pour la chaîne. Une meilleure (OMI) alternative si vous êtes une production la chaîne en premier lieu est d'utiliser le spécificateur de format « r ». Ensuite, la chaîne que vous produisez sera « 1.7976931348623157E + 308 » au lieu, qui analyse ensuite correctement:

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

De toute évidence, ce n'est pas l'aide si vous ne disposez pas de contrôle sur les données -. Mais vous devez comprendre que vous êtes susceptible d'être de perdre des données déjà dans ce cas,

Vous pouvez essayer double.Parse() ou double.TryParse() plutôt que Convert.ToDouble(), mais je ne suis pas certain que vous obtiendrez de meilleurs résultats. Soit dit en passant, la chaîne que vous fournissez est égale à double.MaxValue, qui est (bien sûr) la valeur maximale qui peut être contenue dans un double, de sorte que est probablement où votre erreur vient. types numériques à virgule flottante sont tatillonne, donc je suppose qu'une sorte de l'arrondissement a lieu et en le poussant en dehors des limites du type.

Vous pouvez également essayer le type de données decimal. Vous pouvez avoir une meilleure chance.

Voici ce que je suis venu avec. Merci Jon Skeet et 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;
}

Démontre la question et une solution:

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

Voici une application plus générique qui représente différentes mises en forme et des cultures et plus tolérants:

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

Ce nombre est trop grand pour un double, comme l'exception dit. Vous allez devoir trouver une grande bibliothèque numérique pour gérer que pour vous, car il n'y a rien que je connaisse dans la bibliothèque .Net qui gère un très grand nombre.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top