Мені потрібно проаналізувати рядок "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. Будь-який ви можете використовувати певний набір, якщо ви певні у своєму форматі. наприклад:
NumberStyles.AllowExponent | NumberStyles.Float
decimal d = Decimal.Parse("1.2345E-02", System.Globalization.NumberStyles.Float);
Будьте обережні з обраною відповіддю: існує допоміжна програма, яка вказує System.Globalization.NumberStyles.Float у десятковому.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);
}
Сподіваюся, це комусь допомагає.