2008-12-10 3 views
9

Tôi có một Đôi có giá trị từ khoảng 0,000001 đến 1.000.000.000.000Định dạng kép thành chuỗi trong C#

Tôi muốn định dạng số này thành chuỗi nhưng có điều kiện tùy thuộc vào kích thước của nó. Vì vậy, nếu nó rất nhỏ, tôi muốn định dạng nó với một cái gì đó như:

String.Format("{0:.000000000}", number); 

nếu nó không phải là nhỏ, nói 0,001 sau đó tôi muốn sử dụng cái gì đó như

String.Format("{0:.00000}", number); 

và nếu nó kết thúc, nói 1.000 sau đó định dạng nó là:

String.Format("{0:.0}", number); 

Có cách thông minh để xây dựng chuỗi định dạng này dựa trên kích thước của giá trị tôi định dạng không?

Trả lời

15

Sử dụng Math.Log10 giá trị tuyệt đối của giá trị kép để tìm ra số lượng 0 bạn cần hoặc là trái (nếu dương) hoặc phải (nếu âm) của vị trí thập phân. Chọn chuỗi định dạng dựa trên giá trị này. Bạn sẽ cần xử lý riêng các giá trị bằng không.

string s; 
double epislon = 0.0000001; // or however near zero you want to consider as zero 
if (Math.Abs(value) < epislon) { 
    int digits = Math.Log10(Math.Abs(value)); 
    // if (digits >= 0) ++digits; // if you care about the exact number 
    if (digits < -5) { 
     s = string.Format("{0:0.000000000}", value); 
    } 
    else if (digits < 0) { 
     s = string.Format("{0:0.00000})", value); 
    } 
    else { 
     s = string.Format("{0:#,###,###,##0.000}", value); 
    } 
} 
else { 
    s = "0"; 
} 

Hoặc xây dựng động dựa trên số chữ số.

2

Sử dụng các nhân vật # cho các vị trí tùy chọn trong chuỗi:

string.Format("{0:#,###,##0.000}", number); 

Tôi không nghĩ rằng bạn có thể kiểm soát số lượng chữ số thập phân như thế như độ chính xác của các đôi sẽ có khả năng làm mọi chuyện rối lên.

Để đóng gói logic quyết định số lượng chữ số thập phân để xuất bạn có thể xem xét việc tạo trình định dạng tùy chỉnh.

2

Hai String.Format đầu tiên trong câu hỏi của bạn có thể được giải quyết bằng cách tự động loại bỏ các số không trailing:

String.Format("{0:#,##0.########}", number); 

Và người cuối cùng bạn có thể giải quyết bằng cách gọi Math.round (số 1) cho các giá trị trên 1000 và sau đó sử dụng cùng một String.Format.

Cái gì như:

String.Format("{0:#,##0.########}", number<1000 ? number : Math.Round(number,1)); 
1

Nếu là tôi, tôi muốn viết một lớp wrapper tùy chỉnh và đặt mã tvanfosson của thành phương pháp ToString của nó. Bằng cách đó bạn vẫn có thể làm việc với giá trị kép, nhưng bạn sẽ có được biểu diễn chuỗi bên phải chỉ trong tất cả các trường hợp. Nó trông giống như thế này:

class FormattedDouble 
{ 
    public double Value { get; set; } 

    protected overrides void ToString() 
    { 
     // tvanfosson's code to produce the right string 
    } 
} 

Có thể tốt hơn là tạo cấu trúc, nhưng tôi nghi ngờ nó sẽ tạo nên sự khác biệt lớn. Bạn có thể sử dụng lớp như thế này:

var myDouble = new FormattedDouble(); 
myDouble.Value = Math.Pi; 
Console.WriteLine(myDouble); 
2

Theo dõi trên OwenP (và bằng cách "mở rộng" tvanfosson):

Nếu nó đủ phổ biến, và bạn đang ở trên C# 3.0, tôi muốn biến nó thành một phương pháp mở rộng trên đôi:

class MyExtensions 
{ 
    public static string ToFormmatedString(this double d) 
    { 
     // Take d and implement tvanfosson's code 
    } 
} 

Bây giờ bất cứ nơi nào bạn có một đôi bạn có thể làm:

double d = 1.005343; 
string d_formatted = d.ToFormattedString();