Muszę przeanalizować ciąg „1.2345E-02” (liczba wyrażona w notacji wykładniczej) do dziesiętnego typu danych, ale Decimal.Parse("1.2345E-02")
po prostu zgłasza błąd
Odpowiedzi:
Jest to liczba zmiennoprzecinkowa, musisz jej powiedzieć, że:
decimal d = Decimal.Parse("1.2345E-02", System.Globalization.NumberStyles.Float);
Działa, jeśli określisz NumberStyles.Float
:
decimal x = decimal.Parse("1.2345E-02", NumberStyles.Float);
Console.WriteLine(x); // Prints 0.012345
Nie jestem do końca pewien, dlaczego nie jest to obsługiwane domyślnie - domyślnie NumberStyles.Number
używa się stylów AllowLeadingWhite, AllowTrailingWhite, AllowLeadingSign, AllowTrailingSign, AllowDecimalPoint i AllowThousands. Prawdopodobnie jest to związane z wydajnością; Przypuszczam, że określenie wykładnika jest stosunkowo rzadkie.
decimal
z double
moim kod działa dobrze dla mnie, tak jak ja go spodziewać. Gdybyś mógł podać szczegóły tego, co próbujesz, kod, którego używasz, i wynik, byłoby znacznie łatwiej pomóc.
Oprócz określenia NumberStyles zalecałbym użycie funkcji decimal.TryParse, takiej jak:
decimal result;
if( !decimal.TryParse("1.2345E-02", NumberStyles.Any, CultureInfo.InvariantCulture, out result) )
{
// do something in case it fails?
}
Jako alternatywa dla NumberStyles, możesz użyć określonego zestawu, jeśli masz pewność co do swoich formatów. na przykład:
NumberStyles.AllowExponent | NumberStyles.Float
decimal d = Decimal.Parse("1.2345E-02", System.Globalization.NumberStyles.Float);
Zachowaj ostrożność co do wybranej odpowiedzi: istnieje podtemat określający System.Globalization.NumberStyles.Float w Decimal.Parse, który może prowadzić do wyjątku System.FormatException, ponieważ Twój system może oczekiwać na liczbę sformatowaną za pomocą „,” zamiast „”.
Na przykład w notacji francuskiej „1,2345E-02” jest niepoprawne, należy najpierw przekonwertować je na „1,2345E-02”.
Podsumowując, użyj czegoś podobnego do:
Decimal.Parse(valueString.Replace('.',','), System.Globalization.NumberStyles.Float);
Zauważyłem, że przekazanie NumberStyles.Float
, w niektórych przypadkach, zmienia reguły, według których przetwarzany jest ciąg i skutkuje innym wyjściem z NumberStyles.Number
(domyślne reguły używane przez decimal.Parse
).
Na przykład poniższy kod wygeneruje FormatException
w moim komputerze:
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
Zalecam użycie danych wejściowych NumberStyles.Number | NumberStyles.AllowExponent
, ponieważ pozwoli to na liczby wykładnicze i nadal będzie przetwarzać ciąg zgodnie z decimal
regułami.
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
Aby odpowiedzieć na pytanie autora, właściwą odpowiedzią powinno być:
decimal x = decimal.Parse("1.2345E-02", NumberStyles.Number | NumberStyles.AllowExponent);
Console.WriteLine(x);
Ostrzeżenie dotyczące używania NumberStyles.
„6,33E + 03” jest konwertowane zgodnie z oczekiwaniami na 6330. W języku niemieckim kropki dziesiętne są reprezentowane przecinkami, ale 6,33E + 03 konwertuje do 633000! To problem dla moich klientów, ponieważ kultura generująca dane nie jest znana i może być inna niż kultura operująca na danych. W moim przypadku zawsze używam notacji naukowej, więc zawsze mogę zamienić przecinek na przecinek przed analizą, ale jeśli pracujesz z dowolnymi liczbami, takimi jak ładnie sformatowane liczby, takie jak 1,234,567, to podejście nie działa.
Nie musisz zastępować kropek (odpowiednio przecinków), wystarczy określić wejściowy 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"));
Jeśli chcesz sprawdzić i przekonwertować wartość wykładnika, użyj tego
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);
}
Mam nadzieję, że to komuś pomoże.