Разбор номера из экспоненциального обозначения

Мне нужно проанализировать строку "1.2345E-02" (число, выраженное в экспоненциальной нотации) на десятичный тип данных, но Decimal.Parse("1.2345E-02") просто выдает ошибку

Ответ 1

Это число с плавающей запятой, вы должны сказать, что:

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

Ответ 2

Он работает, если вы укажете NumberStyles.Float:

decimal x = decimal.Parse("1.2345E-02", NumberStyles.Float);
Console.WriteLine(x); // Prints 0.012345

Я не совсем уверен, почему это не поддерживается по умолчанию - по умолчанию используется NumberStyles.Number, который использует стили AllowLeadingWhite, AllowTrailingWhite, AllowLeadingSign, AllowTrailingSign, AllowDecimalPoint и AllowThousands. Возможно, это связано с производительностью; указав экспонента относительно редко, я полагаю.

Ответ 3

В дополнение к указанию NumberStyles я бы рекомендовал использовать функцию decimal.TryParse, такую ​​как:

decimal result;
if( !decimal.TryParse("1.2345E-02", NumberStyles.Any, CultureInfo.InvariantCulture, out result) )
{
     // do something in case it fails?
}

В качестве альтернативы NumberStyles.Any вы можете использовать определенный набор, если вы уверены в своих форматах. например:

NumberStyles.AllowExponent | NumberStyles.Float

Ответ 4

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

Ответ 5

Будьте осторожны с выбранным ответом: есть подтекст, определяющий System.Globalization.NumberStyles.Float в Decimal.Parse, который может привести к исключению System.FormatException, потому что ваша система может ожидать число, образованное с помощью ',' вместо '.

Например, во французском обозначении "1.2345E-02" недействительно, вы должны сначала преобразовать его в "1,2345E-02".

В заключение используйте что-то по строкам:

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

Ответ 6

Я обнаружил, что передача в NumberStyles.Float, в некоторых случаях, изменяет правила, по которым обрабатывается строка, и приводит к другому выводу из NumberStyles.Number (правила по умолчанию, используемые decimal.Parse).

Например, следующий код будет генерировать FormatException в моей машине:

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

Я бы рекомендовал использовать вход NumberStyles.Number | NumberStyles.AllowExponent, так как это позволит экспоненциальные числа и будет обрабатывать строку в соответствии с правилами 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

Чтобы ответить на вопрос о плакате, правильный ответ должен быть:

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

Ответ 7

Предупреждение об использовании NumberStyles.Any:

"6.33E + 03" преобразуется в 6330, как ожидалось. На немецком языке десятичные точки представлены запятыми, но 6,33E + 03 преобразуется в 633000! Это проблема для моих клиентов, поскольку культура, которая генерирует данные, неизвестна и может отличаться от культуры, которая работает с данными. В моем случае у меня всегда есть научная нотация, поэтому я могу всегда заменять запятую на десятичную точку перед разбором, но если вы работаете с произвольными числами, например, в довольно-форматированных числах, таких как 1,234,567, то этот подход не работает.

Ответ 8

Вам не нужно заменять точки (соответственно запятые), просто укажите входной 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"));