2016-04-19 2 views
2

カスタムグループ/桁区切り記号と小数点区切り文字を使用してC#で文字列に数値を書式化したいとします。グループと小数点記号はユーザー入力に基づいて変更できるので、ハードコードされた書式設定文字列の代わりにNumberFormatInfoオブジェクトを使用したいと思います。私のコードは適切な区切り文字を取得しますが、数値の精度を常に小数点以下2桁に変更しますが、必要に応じて小数点以下を表示したいので整数値は小数点以下を持ちません。 。精度を変更せずにカスタムグループと小数点区切り文字でフォーマットする数値

どうすればこの問題を解決できますか?私は "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" 

答えて

3

以下は、私が拡張メソッドとして思い描いた解決策です。

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); 
} 
+0

あなたは私の解決策を 'Replace'と' Trim'または 'LINQ'を使って試しましたか?組み込みのソリューションを探す場合、これらはすべて組み込まれています... – Ian

+0

"### ### ###。###"をパラメータとして指定すると、ソリューションは多くの状況で失敗します。数値の小数点以下の桁数に依存しますNumberFormatInfoオブジェクトの小数点区切り記号とグループ区切り記号にも依存します。たとえば、倍数の値が0.1234になると失敗します私の解決策は常にdoubleと任意のNumberFormatInfoオブジェクトで動作します – tjsmith

+0

私は... LINQの使用を検討するかもしれません。 'LINQ'ソリューションは、あなたが言及している他のソリューションを扱うことができるはずです。 – Ian

0

編集:

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(); 
:そこ

内蔵用いToString()Replace及び/又はTrim(桁プレースホルダ#を使用して)問題を回避あります

組み合わせ私はあなただけをビルトインToString()それを得るためにを使用することはできません推測

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); 

オリジナル:小数点区切りとして,を読むための数値形式でそれをINGのことではないが作業を行います右。あなたはおそらく、あなたが望む結果を得るために、いくつかの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値が第2

  2. n = 1234.499999999999998のようなものかもしれないとき、それはおよそ ToString()です。これは実際にフォーマットするためにのみ使用されます。言い換えれば、あなたがそれをどのように指示するかによって、何かが表示されます。たとえば、小数点区切り文字の後に有効数字2桁の数字を表示するように指示すると、小数点記号の後に有効数字2桁の数字が表示されます。

今、私たちはここにジレンマを持って一緒に二つのものを入れて!あなたがプログラムにしたいことは、「必要なだけ多くの有効数字を表示する」ことです。ただし、double n = 1234.5を入力すると、代わりに1234.499999999999998と表示されます。しかし一方で、小数点記号の後の数字を修正したくない場合もあります。

LINQ SkipWhileReverseを使用する必要があります。単純な組み込みではありません。

関連する問題