Мне нужно преобразовать строку «1.2345E-02» (число, выраженное в экспоненциальной записи) в десятичный тип данных, но Decimal.Parse("1.2345E-02")
просто выдает ошибку
Ответы:
Это число с плавающей запятой, вы должны сказать ему, что:
decimal d = Decimal.Parse("1.2345E-02", System.Globalization.NumberStyles.Float);
Работает, если указать 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. Возможно, это связано с производительностью; Я полагаю, что указание экспоненты относительно редко.
decimal
на double
в моем коде отлично работает для меня, как я и ожидал. Если бы вы могли предоставить подробную информацию о том, что вы пытаетесь сделать, код, который вы используете, и результат, вам было бы намного легче помочь.
В дополнение к указанию 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
Будьте осторожны с выбранным ответом: существует тонкость, указывающая System.Globalization.NumberStyles.Float в Decimal.Parse, что может привести к System.FormatException, потому что ваша система может ожидать числа, отформатированного с помощью ',' вместо ''.
Например, во французской нотации "1.2345E-02" недопустимо, вы должны сначала преобразовать его в "1,2345E-02".
В заключение используйте что-нибудь вроде:
Decimal.Parse(valueString.Replace('.',','), System.Globalization.NumberStyles.Float);
Я обнаружил, что передача в 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);
Предупреждение об использовании NumberStyles.Any:
«6.33E + 03» преобразуется в 6330, как и ожидалось. На немецком языке десятичные точки представлены запятыми, но 6,33E + 03 преобразуется в 633000! Это проблема для моих клиентов, так как культура, генерирующая данные, неизвестна и может отличаться от культуры, которая работает с данными. В моем случае у меня всегда есть научная нотация, поэтому я всегда могу заменить запятую на десятичную точку перед синтаксическим анализом, но если вы работаете с произвольными числами, такими как хорошо отформатированные числа, такие как 1,234,567, тогда этот подход не работает.
Вам не нужно заменять точки (соответственно запятые), просто укажите входной 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"));
Если вы хотите проверить и преобразовать значение экспоненты, используйте это
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);
}
Надеюсь, это кому-то поможет.