[英]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());
原因是因为以下两件事:
首先, double
并不准确。 当你输入像double n = 1234.5
这样的东西时,存储的实际double
值可能是n = 1234.499999999999998
其次,它是关于ToString()
。 它实际上只用于格式化。 换句话说,取决于你如何决定它,它会显示出来。 例如,如果您指示在小数点分隔符后显示带有2位有效数字的数字,那么它将在小数点分隔符后显示正好2位有效数字的数字。
现在,把这两件事放在一起我们就陷入了两难境地 ! 你希望程序做的是:“显示我需要的有效位数”。 但是,当你输入double n = 1234.5
,程序将显示1234.499999999999998
! 但另一方面,您也不希望在小数分隔符后修复数字。
所以,我猜你应该使用LINQ SkipWhile
和Reverse
来做到这一点,而不是简单的内置。
//这是最好的方式:
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.