5

I tried to use the decimal.parse as described at : http://msdn.microsoft.com/en-us/library/cafs243z(v=vs.110).aspx

So i copied from this page the following example:

   string value;
   decimal number;
   value = "1.62345e-02";
   try
   {
       number = Decimal.Parse(value);
       Console.WriteLine("'{0}' converted to {1}.", value, number);
   }
   catch (FormatException)
   {
       Console.WriteLine("Unable to parse '{0}'.", value);
   }

And i got a FormatException, Do you have an idea why it's happened?

thanks, eyal

Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
Eyal leshem
  • 995
  • 2
  • 10
  • 21

2 Answers2

10

shree.pat18's answer is of course right. But I want to explain this question a little bit more if you let me..

Let's look at how Decimal.ToParse(string) method implemented;

public static Decimal Parse(String s)
{
   return Number.ParseDecimal(s, NumberStyles.Number, NumberFormatInfo.CurrentInfo);
}

As you can see, this method uses NumberStyles.Number by default. It is a composite number style and it's implemented like;

Number   = AllowLeadingWhite | AllowTrailingWhite | AllowLeadingSign | AllowTrailingSign |
           AllowDecimalPoint | AllowThousands,

That means your string can have one of;

Since NumberStyles.Number has AllowDecimalPoint, it fits . in your string but this style doesn't have AllowExponent that's why it can't parse e-02 in your string.

That's why you need to use Decimal.Parse Method (String, NumberStyles) overload since you can specify NumberStyles yourself.

Community
  • 1
  • 1
Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
  • 1
    Thanks @SergeyBerezovskiy I try to teach him how to fish instead of give him a fish. – Soner Gönül May 12 '14 at 11:33
  • In most cases (e.g. input coming from files) you will also want to use NumberFormatInfo.InvariantInfo, that is use the overload Parse(String, NumberStyles, IFormatProvider). Regardless of whether you want to use the system culture or an invariant culture case it's best to be specific and pass a NumberFormatInfo argument. The next developer can see immediately what format of decimal points etc. is expected. – Anders Forsgren May 12 '14 at 11:50
  • @AndersForsgren _Unfortunately_, OP never told use what his `CurrentCulture` exactly. That's why I assume his culture uses `.` as a `NumberDecimalSeparator` of his current culture. You have a point about using `IFormatProvider` would be more clear in most cases. But `InvariantInfo` is _culture-independent_. It uses `InvariantCulture` settings. That's why always using `InvariantInfo` might not be a good idea. Of course these all depends on inputs. – Soner Gönül May 12 '14 at 12:03
  • 1
    +1 for the detailed answer and an implicit +1 for the philosophy behind it. – shree.pat18 May 12 '14 at 12:09
  • @SonerGönül I agree we need more details here, but regardless, it is good to be explicit: I recommend passing CurrentCulture even if it is equivalent to omitting the argument. As for Current vs. Invariant, I find 99% of bugs (almost weekly, since I work in a culture with decimal comma) are due to code that didn't think about it and used default (system culture) even though what they meant was to use an InvariantCulture. The opposite kind of bug I have almost never seen! – Anders Forsgren May 12 '14 at 12:37
  • @AndersForsgren If you say so :) – Soner Gönül May 13 '14 at 10:13
6

Try this:

using System.Globalization;
using System.Text;

....

number = Decimal.Parse(value, NumberStyles.AllowExponent|NumberStyles.AllowDecimalPoint);

In order to parse a number in exponential format, you need to set the appropriate flags from NumberStyles Enumeration as described here.

shree.pat18
  • 21,449
  • 3
  • 43
  • 63