Üstel Gösterimden Bir Sayı Ayrıştırma


88

"1.2345E-02" dizesini (üstel gösterimle ifade edilen bir sayı) bir ondalık veri türüne ayrıştırmam gerekiyor, ancak Decimal.Parse("1.2345E-02")yalnızca bir hata veriyor

Yanıtlar:


175

Bu bir kayan nokta sayısıdır, ona şunu söylemelisiniz:

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

50

Şunları belirtirseniz çalışır NumberStyles.Float:

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

Bunun neden varsayılan olarak desteklenmediğinden tam olarak emin değilim - varsayılan, NumberStyles.NumberAllowLeadingWhite, AllowTrailingWhite, AllowLeadingSign, AllowTrailingSign, AllowDecimalPoint ve AllowThousands stillerini kullanan kullanmaktır . Muhtemelen performansla ilgilidir; bir üs belirtmek nispeten nadirdir, sanırım.


Bunu double ile çalıştırmaya çalışıyorum ama öyle görünmüyor. Neden yapamadığından emin değil ..?
Ocak 2019

@JanT: "Olmaz" ve "olamaz" dan daha fazla bilgi olmadan daha fazla yardım edemem. Ne denediğinizi ve tam olarak ne olduğunu gösteren, çok daha detaylı yeni bir soru sormanızı öneririm.
Jon Skeet

Cevabınızdaki gibi kodu çalıştırmayı denedim ama ondalık yerine çift kullanıyorum. Ama zaten geçici çözüm bulundu. Şerefe
Ocak 2019

1
@JanT Geçici çözümünüzü paylaşırsanız iyi olur. Bende tam olarak aynı sorun var ve bilgiyi kullanabilirim. Teşekkürler!
Rick Glimmer

@RickGlimmer: Yapmaya çalıştıkları şeyin ayrıntılarını asla vermedikleri göz önüne alındığında, sorunun JanT ile tam olarak aynı olduğunu nasıl bildiğinden emin değilim. Kodumda decimalile değiştirmek , doublebeklediğim gibi benim için iyi çalışıyor. Verdiğiniz olsaydı ayrıntıları sen çalışıyorsun şeyin, kullandığınız kod ve sonuç, bu yardımı çok daha kolay olurdu.
Jon Skeet

35

NumberStyles'ı belirtmenin yanı sıra, decimal. TryParse işlevini kullanmanızı tavsiye ederim, örneğin:

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

NumberStyles'a alternatif olarak, biçimlerinizden eminseniz, belirli bir set kullanabilirsiniz. Örneğin:

NumberStyles.AllowExponent | NumberStyles.Float

1
Ancak Float'ı AllowExponent ile kullanmak gerekli değildir çünkü Float = AllowLeadingWhite | AllowTrailingWhite | AllowLeadingSign | AllowDecimalPoint | AllowExponent
Lukáš

@ LukášKmoch Gerçekten haklısın. Diğerleri gibi (Herhangi biri dışında) alışkanlık gücü onu kapsamaz. Fazladan ameliyathane yapmaktan zarar gelmemeli.
Sverrir Sigmundarson

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

9

Seçilen yanıt konusunda dikkatli olun: System.Globalization.NumberStyles.Float in Decimal.Parse öğesini belirten bir alt yetenek vardır ve bu bir System.FormatException sonucuna yol açabilir çünkü sisteminiz "yerine", "ile biçimlendirilmiş bir sayı bekliyor olabilir.

Örneğin, fransızca gösterimde "1.2345E-02" geçersizdir, önce "1,2345E-02" ye dönüştürmelisiniz.

Sonuç olarak, şu satırlar boyunca bir şey kullanın:

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

1
Kesinlikle haklısın. Neden başka kimsenin açmadığını anlamıyorum
Carles Alcolea

10
CultureInfo.InvariantCulture'ı
Parse'ın

4

NumberStyles.FloatBazı durumlarda içeri aktarmanın, dizenin işlendiği kuralları değiştirdiğini ve bundan farklı bir çıktıyla sonuçlandığını buldum NumberStyles.Number(tarafından kullanılan varsayılan kurallardecimal.Parse ).

Örneğin, aşağıdaki kod FormatExceptionmakinemde bir oluşturacak :

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

Girişi kullanmanızı tavsiye ederim NumberStyles.Number | NumberStyles.AllowExponent , çünkü bu üstel sayılara izin verecek ve dizeyi decimalkurallara göre işleyecektir .

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

Posterin sorusuna cevap vermek için doğru cevap şu şekilde olmalıdır:

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

1

NumberStyles.Any kullanımıyla ilgili uyarı:

"6.33E + 03", beklendiği gibi 6330'a dönüşür. Almanca'da ondalık basamaklar virgülle temsil edilir, ancak 6,33E + 03 633000'e dönüştürülür! Verileri oluşturan kültür bilinmediğinden ve veriler üzerinde işleyen kültürden farklı olabileceğinden, bu müşterilerim için bir sorundur. Benim durumumda, her zaman bilimsel gösterime sahibim, bu yüzden ayrıştırmadan önce her zaman virgül yerine ondalık virgül koyabilirim, ancak 1,234,567 gibi güzel biçimlendirilmiş sayılar gibi keyfi sayılarla çalışıyorsanız, o zaman bu yaklaşım işe yaramaz.


0

Noktaları (sırasıyla virgül) değiştirmeniz gerekmez, sadece IFormatProvider girişini belirtin:

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

Üs değerini kontrol etmek ve dönüştürmek istiyorsanız bunu kullanın

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

Umarım bu birine yardımcı olur.


0

Varsayılan NumberStyleiçin decimal.Parse(String), NumberStyles.Numberüslere izin vermek için işlevselliği eklemek istiyorsanız, eklemek için bit düzeyinde VEYA yapabilirsiniz NumberStyles.AllowExponent.

decimal d = decimal
    .Parse("1.2345E-02", NumberStyles.Number | NumberStyles.AllowExponent);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.