簡體   English   中英

使用自定義組和小數分隔符將數字格式化為字符串而不更改精度

[英]Format number to string with custom group and decimal separator without changing precision

我想使用自定義組/千位分隔符和小數分隔符將一些數字格式化為C#中的字符串。 組和小數分隔符可以根據用戶輸入進行更改,因此我想使用NumberFormatInfo對象而不是硬編碼格式字符串。 我的下面的代碼得到了正確的分隔符,但它將數字的精度更改為始終為兩位小數,而我想保持數字的完整精度,並且只在需要時顯示小數位(因此整數值不具有小數位) 。

我怎樣才能做到這一點? 我猜我需要更改“N”參數,但將其更改為什么?

double n1 = 1234;
double n2 = 1234.5;
double n3 = 1234567.89;
double n4 = 1234.567;

var nfi = new NumberFormatInfo();
nfi.NumberDecimalSeparator = ",";
nfi.NumberGroupSeparator = " ";

string s1 = n1.ToString("N", nfi); //want "1 234" but I get "1 234,00"
string s2 = n2.ToString("N", nfi); //want "1 234,5" but I get "1 234,50"
string s3 = n3.ToString("N", nfi); //correct output of "1 234 567,89" 
string s4 = n4.ToString("N", nfi); //want " 1 234,567" but I get "1 234,57"

以下是我提出的解決方案作為擴展方法。

public static string Format(this double d, NumberFormatInfo numberFormatInfo)
{
    string s = d.ToString(CultureInfo.InvariantCulture);
    int index = s.IndexOf('.');
    int decimalPlaces = index == -1 ? 0 : s.Length - index - 1;
    return d.ToString($"N{decimalPlaces}", numberFormatInfo);
}

編輯:

使用內置的解決方法ToString()通過使用數字占位符# Replace 和/或 Trim

double n1 = 1234;
double n2 = 1234.5;
double n3 = 1234567.89;
double n4 = 1234.567;
string s1 = n1.ToString("### ### ###.###").Replace(".",",").Trim();
string s2 = n2.ToString("### ### ###.###").Replace(".", ",").Trim();
string s3 = n3.ToString("### ### ###.###").Replace(".", ",").Trim();
string s4 = n4.ToString("### ### ###.###").Replace(".", ",").Trim();

將它與數字格式結合起來讀取,因為小數分隔符不起作用

double n1 = 1234;
double n2 = 1234.5;
double n3 = 1234567.89;
double n4 = 1234.567;

var nfi = new NumberFormatInfo();
nfi.NumberDecimalSeparator = ",";
nfi.NumberGroupSeparator = " ";

string s1 = n1.ToString("### ### ###,###", nfi); //doesn't work
string s2 = n2.ToString("### ### ###,###", nfi);
string s3 = n3.ToString("### ### ###,###", nfi);
string s4 = n4.ToString("### ### ###,###", nfi);

原版的:

我想你不能使用內置的ToString()來使它正確。 你可能需要一些LINQ技巧來獲得你想要的結果:

double n1 = 1234;
double n2 = 1234.5;
double n3 = 1234567.89;
double n4 = 1234.567;

var nfi = new NumberFormatInfo();
nfi.NumberDecimalSeparator = ",";
nfi.NumberGroupSeparator = " ";

string s1 = new string(n1.ToString("N", nfi).Reverse().SkipWhile(x => x == '0' || x == ',').Reverse().ToArray());
string s2 = new string(n2.ToString("N", nfi).Reverse().SkipWhile(x => x == '0' || x == ',').Reverse().ToArray());
string s3 = new string(n3.ToString("N", nfi).Reverse().SkipWhile(x => x == '0' || x == ',').Reverse().ToArray());
string s4 = new string(n4.ToString("N", nfi).Reverse().SkipWhile(x => x == '0' || x == ',').Reverse().ToArray());

原因是因為以下兩件事:

  1. 首先, double 並不准確。 當你輸入像double n = 1234.5這樣的東西時,存儲的實際double值可能是n = 1234.499999999999998

  2. 其次,它是關於ToString() 它實際上只用於格式化。 換句話說,取決於你如何決定它,它會顯示出來。 例如,如果您指示在小數點分隔符后顯示帶有2位有效數字的數字,那么它將在小數點分隔符后顯示正好2位有效數字的數字。

現在,把這兩件事放在一起我們就陷入了兩難境地 你希望程序做的是:“顯示我需要的有效位數”。 但是,當你輸入double n = 1234.5 ,程序將顯示1234.499999999999998 但另一方面,您也不希望在小數分隔符后修復數字。

所以,我猜你應該使用LINQ SkipWhileReverse來做到這一點,而不是簡單的內置。

//這是最好的方式:

s3 = n3.ToString($“### ## 0 {CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator} 00”);

//或者我更喜歡:

s3 = n3.ToString($“### {CultureInfo.CurrentCulture.NumberFormat.NumberGroupSeparator} ## 0 {CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator} 00”);

//我一直在用這個 NOP。 這是最好和最小的方式。 :) //最好的祝福。 Ersin Kecis。

您可以增加NumberFormatInfo中的小數位數,並使用TrimEnd()刪除其他零和分隔符。

    nfi.NumberDecimalDigits = 15;

    public static string FormatDouble(double d, NumberFormatInfo nfi)
    {
        return d.ToString("N", nfi).TrimEnd('0', ' ', ',', '.');
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM