Tôi cần phân tích cú pháp chuỗi "1.2345E-02" (một số được biểu thị bằng ký hiệu hàm mũ) thành kiểu dữ liệu thập phân, nhưng Decimal.Parse("1.2345E-02")
chỉ cần tạo ra một lỗi
Câu trả lời:
Nó là một số dấu phẩy động, bạn phải nói với nó rằng:
decimal d = Decimal.Parse("1.2345E-02", System.Globalization.NumberStyles.Float);
Nó hoạt động nếu bạn chỉ định NumberStyles.Float
:
decimal x = decimal.Parse("1.2345E-02", NumberStyles.Float);
Console.WriteLine(x); // Prints 0.012345
Tôi không hoàn toàn chắc chắn tại sao điều này không được hỗ trợ theo mặc định - mặc định là sử dụng NumberStyles.Number
, sử dụng các kiểu AllowLeadingWhite, AllowTrailingWhite, AllowLeadingSign, AllowTrailingSign, AllowDecimalPoint và AllowThollionss. Có thể nó liên quan đến hiệu suất; Tôi cho rằng việc chỉ định một số mũ là tương đối hiếm.
decimal
bằng double
trong mã của tôi hoạt động tốt đối với tôi, giống như tôi mong đợi. Nếu bạn có thể cung cấp chi tiết về những gì bạn đang cố gắng, mã bạn đang sử dụng và kết quả, thì việc trợ giúp sẽ dễ dàng hơn nhiều.
Ngoài việc chỉ định NumberStyles, tôi khuyên bạn nên sử dụng hàm decimal.TryParse chẳng hạn như:
decimal result;
if( !decimal.TryParse("1.2345E-02", NumberStyles.Any, CultureInfo.InvariantCulture, out result) )
{
// do something in case it fails?
}
Để thay thế cho NumberStyles, bạn có thể sử dụng một tập hợp cụ thể nếu bạn chắc chắn về các định dạng của mình. ví dụ:
NumberStyles.AllowExponent | NumberStyles.Float
decimal d = Decimal.Parse("1.2345E-02", System.Globalization.NumberStyles.Float);
Hãy thận trọng với câu trả lời đã chọn: có một tiện ích con chỉ định System.Globalization.NumberStyles.Float ở dạng Decimal.Parse có thể dẫn đến System.FormatException vì hệ thống của bạn có thể đang chờ một số được định dạng bằng ',' thay vì '.'
Ví dụ: trong ký hiệu tiếng Pháp, "1.2345E-02" không hợp lệ, trước tiên bạn phải chuyển đổi nó thành "1.2345E-02".
Tóm lại, hãy sử dụng một cái gì đó dọc theo các dòng:
Decimal.Parse(valueString.Replace('.',','), System.Globalization.NumberStyles.Float);
Tôi thấy rằng việc chuyển vào NumberStyles.Float
, trong một số trường hợp, thay đổi các quy tắc mà chuỗi được xử lý và dẫn đến kết quả đầu ra khác với NumberStyles.Number
(các quy tắc mặc định được sử dụng bởi decimal.Parse
).
Ví dụ: mã sau sẽ tạo FormatException
trong máy của tôi:
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
Tôi khuyên bạn nên sử dụng đầu vào NumberStyles.Number | NumberStyles.AllowExponent
, vì điều này sẽ cho phép số mũ và sẽ vẫn xử lý chuỗi theo các decimal
quy tắc.
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
Để trả lời câu hỏi của người đăng, câu trả lời đúng thay vào đó là:
decimal x = decimal.Parse("1.2345E-02", NumberStyles.Number | NumberStyles.AllowExponent);
Console.WriteLine(x);
Cảnh báo về việc sử dụng NumberStyles.Any:
"6.33E + 03" chuyển đổi thành 6330 như mong đợi. Trong tiếng Đức, dấu thập phân được biểu thị bằng dấu phẩy, nhưng 6,33E + 03 chuyển thành 633000! Đây là một vấn đề đối với khách hàng của tôi, vì văn hóa tạo ra dữ liệu không được biết đến và có thể khác với văn hóa đang hoạt động trên dữ liệu. Trong trường hợp của tôi, tôi luôn có ký hiệu khoa học, vì vậy tôi luôn có thể thay thế dấu phẩy thành dấu thập phân trước khi phân tích cú pháp, nhưng nếu bạn đang làm việc với các số tùy ý, như các số có định dạng đẹp như 1.234.567 thì cách tiếp cận đó không hoạt động.
Bạn không cần thay thế các dấu chấm (tương ứng là dấu phẩy) chỉ cần chỉ định IFormatProvider đầu vào:
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"));
Nếu bạn muốn kiểm tra và chuyển đổi giá trị lũy thừa, hãy sử dụng
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);
}
Hy vọng điều này sẽ giúp ai đó.