Разобрать число из экспоненциальной записи - PullRequest
74 голосов
/ 07 октября 2010

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

Ответы [ 8 ]

154 голосов
/ 07 октября 2010

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

decimal d = Decimal.Parse("1.2345E-02", System.Globalization.NumberStyles.Float);
44 голосов
/ 07 октября 2010

Работает, если указать 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. Возможно, это связано с производительностью; указание показателя степени относительно редко, я полагаю.

31 голосов
/ 27 февраля 2012

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

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

В качестве альтернативы NumberStyles.установить, если вы уверены, что ваши форматы.например:

NumberStyles.AllowExponent | NumberStyles.Float
11 голосов
/ 07 октября 2010
decimal d = Decimal.Parse("1.2345E-02", System.Globalization.NumberStyles.Float);
7 голосов
/ 21 ноября 2016

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

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

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

Decimal.Parse(valueString.Replace('.',','), System.Globalization.NumberStyles.Float);
3 голосов
/ 09 марта 2017

Я обнаружил, что передача 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);
1 голос
/ 19 декабря 2015

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

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

0 голосов
/ 26 июня 2019

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