2008-12-10 61 views
9

字符串我有一個雙重這可能會對從大約0.000001至1,000,000,000.000格式雙象在C#

我想格式化這個數字作爲一個字符串,但有條件地取決於其大小的值。所以,如果這是非常小的我想它的東西,如格式化:

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

如果它不是那麼小,說0.001那麼我想使用類似

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

,如果它已經結束了,說1000然後格式化爲:

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

有沒有一種巧妙的方法來構建基於我要格式化值的大小的格式字符串?

回答

15

使用double的絕對值的Math.Log10來計算出您需要在小數點左邊(如果爲正數)或右邊(如果是負數)需要多少個0。根據此值選擇格式字符串。你需要分別處理零值。

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

或者根據位數動態構造它。

2

使用可選位置#字符字符串中:

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

我不認爲你可以控制小數像爲一體的雙會容易誤事精度的數量。

爲了封裝決定輸出多少小數位的邏輯,您可以查看創建自定義格式器的信息。

2

在你的問題前兩個的String.Format可以通過自動刪除尾隨零來解決:在1000

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

,最後一個,你可以通過調用Math.Round解決(數量,1)值然後使用相同的String.Format。

喜歡的東西:

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

如果是我,我會寫一個定製的包裝類,並把tvanfosson的代碼放入其ToString方法。這樣你仍然可以使用double值,但是在幾乎所有情況下你都會得到正確的字符串表示。它看起來像這樣:

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

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

也許它可能會更好,使它成爲一個結構,但我懷疑這會造成很大的差異。你可以使用類是這樣的:

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

上OwenP的(和「擴展」 tvanfosson)隨訪:

如果它是很常見的,你是基於C#3。0,我把它變成一個擴展方法上雙:

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

現在任何地方,你有雙重你可以這樣做:

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