web-dev-qa-db-ja.com

指数表記から数値を解析する

文字列 "1.2345E-02"(指数表記で表される数値)を10進データ型に解析する必要がありますが、Decimal.Parse("1.2345E-02")は単にエラーをスローします

76
Jimbo

これは浮動小数点数です。次のことを伝えなければなりません。

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

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スタイルを使用します。おそらくパフォーマンスに関連しています。指数を指定することは比較的まれです、と思います。

44
Jon Skeet

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
32
decimal d = Decimal.Parse("1.2345E-02", System.Globalization.NumberStyles.Float);
11
Mitch Wheat

選択された答えに注意してください:System.Globalization.NumberStyles.FloatDecimal.Parseで指定する繊細さがありますこれはSystem.FormatExceptionにつながる可能性があります。これは、システムが「、」ではなく「、」 「。」

たとえば、フランス語表記では、「1.2345E-02」は無効です。最初に「1,2345E-02」に変換する必要があります。

結論として、次のラインに沿って何かを使用します。

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

NumberStyles.Floatを渡すと、場合によっては、文字列が処理されるルールが変更され、NumberStyles.Numberdecimal.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);
3
bastos.sergio

NumberStyles.Anyの使用に関する警告:

「6.33E + 03」は、予想どおり6330に変換されます。ドイツ語では、小数点はコンマで表されますが、6,33E + 03は633000に変換されます!データを生成するカルチャは不明であり、データを操作しているカルチャとは異なる可能性があるため、これは顧客にとって問題です。私の場合、常に科学表記法があるため、解析する前にコンマを常に小数点に置き換えることができますが、1,234,567のようなきれいにフォーマットされた数字のような任意の数字を使用している場合、そのアプローチは機能しません。

1
David Kitzinger

指数値を確認して変換する場合は、これを使用します

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

これが誰かを助けることを願っています。

0
rAm

入力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
mortal