Pregunta

Tengo que 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 emite un error

¿Fue útil?

Solución

Es un número de coma flotante, hay que decirle que:

decimal d = Decimal.Parse("1.2345E-02", System.Globalization.NumberStyles.Float);

Otros consejos

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 está soportado por defecto - el valor por defecto es utilizar NumberStyles.Number, que utiliza el AllowLeadingWhite, AllowTrailingWhite, AllowLeadingSign, AllowTrailingSign, AllowDecimalPoint y estilos AllowThousands. Posiblemente es variable; especificando un exponente es relativamente raro, supongo.

Además de especificar los NumberStyles lo recomiendo que utilice el decimal.TryParse función, 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.Any que podría utilizar un conjunto específico si está seguro de sus formatos. por ejemplo:

NumberStyles.AllowExponent | NumberStyles.Float
decimal d = Decimal.Parse("1.2345E-02", System.Globalization.NumberStyles.Float);

Sea cauteloso sobre la respuesta seleccionada: hay una sutileza que especifica System.Globalization.NumberStyles.Float en Decimal.Parse lo que podría conducir a un Sistema. FormatException debido a que su sistema podría estar esperando un número formateado con '' en lugar de ''.

Por ejemplo, en la notación francés, "1.2345E-02" no es válido, tiene que convertirlo en "1,2345E-02" en primer lugar.

En conclusión, el uso de algo en la línea de:

Decimal.Parse(valueString.Replace('.',','), System.Globalization.NumberStyles.Float);

he encontrado que pasa en NumberStyles.Float, en algunos casos, los cambios de las reglas por las que la cadena se procesa y resulta en una salida diferente de NumberStyles.Number (las reglas predeterminadas utilizadas por decimal.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

Me gustaría recomendar el uso del NumberStyles.Number | NumberStyles.AllowExponent de entrada, ya que esto permitirá números exponenciales y todavía procesará la cadena bajo las reglas decimal.

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 en su lugar:

decimal x = decimal.Parse("1.2345E-02", NumberStyles.Number | NumberStyles.AllowExponent);
Console.WriteLine(x);

Advertencia sobre el uso de NumberStyles.Any:

"6.33E + 03" conversos al 6330 como se esperaba. En alemán, los decimales se representan por comas, pero 6,33E + 03 convertidos a 633000! Esto es un problema para mis clientes, como la cultura que genera los datos no se conoce y puede ser diferente de la cultura que está operando en los datos. En mi caso, siempre tengo la notación científica, por lo que siempre se puede sustituir por comas a punto decimal antes del análisis, pero si se está trabajando con números arbitrarios, como los números bastante con formato similar a 1.234.567 continuación, ese enfoque no funciona.

no es necesario reemplazar los puntos (respectivamente las comas) acaba de especificar el IFormatProvider de entrada:

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 comprobar y convertir el uso de este valor del exponente

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.

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