Мне нужно проанализировать строку "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"));