Pregunta

Tengo esta cadena "1.79769313486232E + 308" y estoy tratando de convertirlo en un valor numérico .NET (doble?), Pero estoy recibiendo la excepción a continuación. Estoy usando Convert.ToDouble(). ¿Cuál es la forma correcta de hacer esta conversión?

  

OverflowException: Valor fue demasiado grandes o demasiado pequeñas para un doble

¿Fue útil?

Solución

es el problema probablemente debido al hecho de que Double.MaxValue se convierte en una cadena, y cuando la cadena es de salida, no todos los dígitos son de salida, sino que es redondeada. Analizar este valor desborda el doble.

El uso de Double.TryParse y posteriormente comprobar la igualdad en la cadena "1.79769313486232E + 308" en caso de fallo y Double.MaxValue sustitución debe ser una solución rápida, si es necesario para mantener la cadena de la manera que es.

EDIT: Por supuesto, si no es necesario para mantener la cadena de la manera que es, utilice el formato de ida y vuelta especificador para producir la cadena en el primer lugar, como Jon describe en su respuesta .

Otros consejos

Desafortunadamente, este valor es mayor que double.MaxValue, por lo tanto, la excepción.

Como codekaizen sugiere, podría difícil que el código de una prueba para la cadena. Una alternativa mejor (OMI) si usted es el que producir la cadena en el primer lugar es el uso de la "r" especificador de formato. A continuación, la cadena que produzca será "1.7976931348623157E + 308" en cambio, que luego analiza correctamente:

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

Obviamente eso no ayuda si usted no tiene control sobre los datos -. Pero entonces usted debe entender que es probable que sea la pérdida de datos ya que en ese caso

Puede intentar double.Parse() o double.TryParse() en lugar de Convert.ToDouble(), pero no estoy seguro de que va a obtener mejores resultados. Por cierto, la cadena que se proporciona es igual a double.MaxValue, que es (por supuesto) el valor máximo que puede estar contenida en un doble, por lo que es probable cuando el error está viniendo. Coma flotante tipos numéricos son meticulosos, lo que podría suponer que una especie de redondeo está llevando a cabo y empujándolo fuera de los límites del tipo.

También puede probar el tipo de datos decimal. Es posible que tenga mejor suerte que hay.

Esto es lo que me ocurrió. Gracias Jon Skeet y 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;
}

Demuestra el problema y la solución:

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

Aquí una aplicación más genérica que representan diferentes formato y culturas y es más tolerante:

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

Ese número es demasiado grande para un doble, como dice la excepción. Usted va a tener que encontrar una biblioteca número grande como para manejar eso para usted, ya que no hay nada que yo sepa en la biblioteca .Net que maneja números muy grandes.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top