Parse a Number from Exponential Notation

C#.NetNumber FormattingExponent

C# Problem Overview


I need to parse the string "1.2345E-02" (a number expressed in exponential notation) to a decimal data type, but Decimal.Parse("1.2345E-02") simply throws an error

C# Solutions


Solution 1 - C#

It is a floating point number, you have to tell it that:

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

Solution 2 - C#

It works if you specify NumberStyles.Float:

decimal x = decimal.Parse("1.2345E-02", NumberStyles.Float);
Console.WriteLine(x); // Prints 0.012345

I'm not entirely sure why this isn't supported by default - the default is to use NumberStyles.Number, which uses the AllowLeadingWhite, AllowTrailingWhite, AllowLeadingSign, AllowTrailingSign, AllowDecimalPoint, and AllowThousands styles. Possibly it's performance-related; specifying an exponent is relatively rare, I suppose.

Solution 3 - C#

In addition to specifying the NumberStyles I would recommend that you use the decimal.TryParse function such as:

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

As an alternative to NumberStyles.Any you could use a specific set if you're certain of your formats. e.g:

NumberStyles.AllowExponent | NumberStyles.Float

Solution 4 - C#

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

Solution 5 - C#

Be cautious about the selected answer: there is a subtility specifying System.Globalization.NumberStyles.Float in Decimal.Parse which could lead to a System.FormatException because your system might be awaiting a number formated with ',' instead of '.'

For instance, in french notation, "1.2345E-02" is invalid, you have to convert it to "1,2345E-02" first.

In conclusion, use something along the lines of:

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

Solution 6 - C#

The default NumberStyle for decimal.Parse(String) is NumberStyles.Number, so if you just want to add the functionality to allow exponents, then you can do a bitwise OR to include NumberStyles.AllowExponent.

decimal d = decimal
    .Parse("1.2345E-02", NumberStyles.Number | NumberStyles.AllowExponent);

Solution 7 - C#

I've found that passing in NumberStyles.Float, in some cases, changes the rules by which the string is processed and results in a different output from NumberStyles.Number (the default rules used by decimal.Parse).

For example, the following code will generate a FormatException in my machine:

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

I'd recommend using the input NumberStyles.Number | NumberStyles.AllowExponent, as this will allow exponential numbers and will still process the string under the decimal rules.

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

To answer the poster's question, the right answer should instead be:

decimal x = decimal.Parse("1.2345E-02", NumberStyles.Number | NumberStyles.AllowExponent);
Console.WriteLine(x);

Solution 8 - C#

Warning about using NumberStyles.Any:

"6.33E+03" converts to 6330 as expected. In German, decimal points are represented by commas, but 6,33E+03 converts to 633000! This is a problem for my customers, as the culture that generates the data is not known and may be different than the culture that is operating on the data. In my case, I always have scientific notation, so I can always replace comma to decimal point before parsing, but if you are working with arbitrary numbers, like pretty-formatted numbers like 1,234,567 then that approach doesn't work.

Solution 9 - C#

You don't need to replace the dots (respectively the commas) just specify the input 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"));

Solution 10 - C#

If you want to check and convert the exponent value use this

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

Hope this helps someone.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJimboView Question on Stackoverflow
Solution 1 - C#Hans PassantView Answer on Stackoverflow
Solution 2 - C#Jon SkeetView Answer on Stackoverflow
Solution 3 - C#Sverrir SigmundarsonView Answer on Stackoverflow
Solution 4 - C#Mitch WheatView Answer on Stackoverflow
Solution 5 - C#KwentRellView Answer on Stackoverflow
Solution 6 - C#Joe PhillipsView Answer on Stackoverflow
Solution 7 - C#bastos.sergioView Answer on Stackoverflow
Solution 8 - C#David KitzingerView Answer on Stackoverflow
Solution 9 - C#mortalView Answer on Stackoverflow
Solution 10 - C#rAmView Answer on Stackoverflow