Necesito analizar la cadena "1.2345E-02" (un número expresado en notación exponencial) a un tipo de datos decimal, pero Decimal.Parse("1.2345E-02")
simplemente arroja un error
Respuestas:
Es un número de coma flotante, tienes que decirle que:
decimal d = Decimal.Parse("1.2345E-02", System.Globalization.NumberStyles.Float);
Funciona si especifica NumberStyles.Float
:
decimal x = decimal.Parse("1.2345E-02", NumberStyles.Float);
Console.WriteLine(x); // Prints 0.012345
No estoy del todo seguro de por qué esto no es compatible de forma predeterminada: el valor predeterminado es usar NumberStyles.Number
, que usa los estilos AllowLeadingWhite, AllowTrailingWhite, AllowLeadingSign, AllowTrailingSign, AllowDecimalPoint y AllowThousands. Posiblemente esté relacionado con el rendimiento; especificar un exponente es relativamente raro, supongo.
decimal
con double
en mi código bien funciona para mí, así como yo esperaría que lo haga. Si pudiera proporcionar detalles de lo que está intentando, el código que está utilizando y el resultado, sería mucho más fácil ayudar.
Además de especificar los NumberStyles, le recomendaría que utilice la función decimal.TryParse como:
decimal result;
if( !decimal.TryParse("1.2345E-02", NumberStyles.Any, CultureInfo.InvariantCulture, out result) )
{
// do something in case it fails?
}
Como alternativa a NumberStyles, cualquiera puede usar un conjunto específico si está seguro de sus formatos. p.ej:
NumberStyles.AllowExponent | NumberStyles.Float
decimal d = Decimal.Parse("1.2345E-02", System.Globalization.NumberStyles.Float);
Tenga cuidado con la respuesta seleccionada: hay una sutileza que especifica System.Globalization.NumberStyles.Float en Decimal.Parse que podría llevar a una System.FormatException porque su sistema podría estar esperando un número formateado con ',' en lugar de '.'
Por ejemplo, en la notación francesa, "1.2345E-02" no es válido, primero debe convertirlo a "1,2345E-02".
En conclusión, use algo como:
Decimal.Parse(valueString.Replace('.',','), System.Globalization.NumberStyles.Float);
Descubrí que pasar NumberStyles.Float
, en algunos casos, cambia las reglas por las cuales se procesa la cadena y da como resultado una salida diferente de NumberStyles.Number
(las reglas predeterminadas utilizadas pordecimal.Parse
).
Por ejemplo, el siguiente código generará un FormatException
en mi máquina:
CultureInfo culture = new CultureInfo("");
culture.NumberFormat.NumberDecimalDigits = 2;
culture.NumberFormat.NumberDecimalSeparator = ".";
culture.NumberFormat.NumberGroupSeparator = ",";
Decimal.Parse("1,234.5", NumberStyles.Float, culture); // FormatException thrown here
Recomendaría usar la entrada NumberStyles.Number | NumberStyles.AllowExponent
, ya que esto permitirá números exponenciales y aún procesará la cadena según las decimal
reglas.
CultureInfo culture = new CultureInfo("");
culture.NumberFormat.NumberDecimalDigits = 2;
culture.NumberFormat.NumberDecimalSeparator = ".";
culture.NumberFormat.NumberGroupSeparator = ",";
Decimal.Parse("1,234.5",NumberStyles.Number | NumberStyles.AllowExponent, culture); // Does not generate a FormatException
Para responder a la pregunta del cartel, la respuesta correcta debería ser:
decimal x = decimal.Parse("1.2345E-02", NumberStyles.Number | NumberStyles.AllowExponent);
Console.WriteLine(x);
Advertencia sobre el uso de NumberStyles.
"6.33E + 03" se convierte en 6330 como se esperaba. En alemán, los puntos decimales se representan con comas, ¡pero 6,33E + 03 se convierte en 633000! Esto es un problema para mis clientes, ya que la cultura que genera los datos no es conocida y puede ser diferente a la cultura que opera sobre los datos. En mi caso, siempre tengo notación científica, por lo que siempre puedo reemplazar la coma por el punto decimal antes de analizar, pero si está trabajando con números arbitrarios, como números con formato bonito como 1,234,567, entonces ese enfoque no funciona.
No necesita reemplazar los puntos (respectivamente las comas), solo especifique la entrada IFormatProvider:
float d = Single.Parse("1.27315", System.Globalization.NumberStyles.Float, new CultureInfo("en-US"));
float d = Single.Parse("1,27315", System.Globalization.NumberStyles.Float, new CultureInfo("de-DE"));
Si desea verificar y convertir el valor del exponente, use este
string val = "1.2345E-02";
double dummy;
bool hasExponential = (val.Contains("E") || val.Contains("e")) && double.TryParse(val, out dummy);
if (hasExponential)
{
decimal d = decimal.Parse(val, NumberStyles.Float);
}
Espero que esto ayude a alguien.