Проаналізуйте число з експоненціальних позначень


85

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

Відповіді:


169

Це число з плаваючою комою, ви повинні сказати йому, що:

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

49

Це працює, якщо вказати 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. Можливо, це пов'язано з продуктивністю; вказівка ​​показника є відносно рідкісною, я гадаю.


Я намагаюся змусити це працювати з подвійним, але, здається, це не буде. Не впевнені, чому це не могло ..?
19

@JanT: Не маючи більше інформації, ніж "це не буде" і "це не могло", я не можу допомогти більше. Я пропоную вам задати нове запитання набагато детальніше, показуючи, що ви пробували і що саме сталося.
Джон Скіт,

Я намагався запустити код, як у вашій відповіді, але замість десяткового використав double. Але вже знайшов обхідний шлях. Вітання
19

1
@JanT Було б непогано, якби ви могли поділитися своїм обхідним шляхом. У мене точно така ж проблема, і я міг би використовувати інформацію. Дякую!
Рік Гліммер,

@RickGlimmer: Я не впевнений, наскільки ви знаєте, що ваша проблема точно така ж, як у JanT, враховуючи те, що вони ніколи не надавали деталей того, що намагалися зробити. Заміна decimalз doubleв моєму коді відмінно працює для мене, так само , як я б очікувати , що це. Якби ви могли надати деталі того, що ви намагаєтесь, код, який ви використовуєте, і результат, було б набагато простіше допомогти.
Джон Скіт,

34

Окрім зазначення 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

1
Але не потрібно використовувати Float з AllowExponent, оскільки Float = AllowLeadingWhite | AllowTrailingWhite | AllowLeadingSign | AllowDecimalPoint | AllowExponent
Лукаш

@ LukášKmoch Справді, ти маєш рацію. Сила звички, як інші (крім будь-якої), не включає її. Хоча не завадить виконати додаткове АБО.
Сверрір Зігмундарсон,


8

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

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

На закінчення використовуйте щось на зразок:

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

1
Ви абсолютно праві. Я не розумію, чому ніхто інший цього не вигадав.
Carles Alcolea

10
Краще використовувати CultureInfo.InvariantCulture як 3-й параметр розбору
Андрій Козачук

3

Я виявив, що передача 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

Попередження про використання NumberStyles.Any:

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


0

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

0

Якщо ви хочете перевірити та перетворити значення показника, використовуйте це

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);
}

Сподіваюся, це комусь допомагає.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.