C# 十进制为带千的字符串';什么是分离器?
考虑一个C# 十进制为带千的字符串';什么是分离器?,c#,.net,localization,globalization,C#,.net,Localization,Globalization,考虑一个Decimal值: Decimal value = -1234567890.1234789012M; 我想将这个Decimal值转换成一个字符串,并包含“数千个分隔符” 注意:我不想包括千位分隔符,我想包括数字分组。这种差异对于不将数字分组为数千或不使用逗号分隔组的文化非常重要 在我的计算机上,使用我当前的语言环境,使用不同标准格式字符串的一些示例输出: value.ToString() = -1234567890..1234789012 (Implicit Gen
Decimal
值:
Decimal value = -1234567890.1234789012M;
我想将这个Decimal
值转换成一个字符串,并包含“数千个分隔符”
注意:我不想包括千位分隔符,我想包括数字分组。这种差异对于不将数字分组为数千或不使用逗号分隔组的文化非常重要
在我的计算机上,使用我当前的语言环境,使用不同标准格式字符串的一些示例输出:
value.ToString() = -1234567890..1234789012 (Implicit General)
value.ToString("g") = -1234567890..1234789012 (General)
value.ToString("d") = FormatException (Decimal whole number)
value.ToString("e") = -1..234568e++009 (Scientific)
value.ToString("f") = -1234567890..123 (Fixed Point)
value.ToString("n") = -12,,3456,,7890..123 (Number with commas for thousands)
value.ToString("r") = FormatException (Round trippable)
value.ToString("c") = -$$12,,3456,,7890..123 (Currency)
value.ToString("#,0.#") = -12,,3456,,7890..1
我想要的(取决于文化)是:
如何将十进制
转换为带有数字分组的字符串
更新:使用我当前的文化,一些更理想的输出:
-1234567890M --> -12,,3456,,7890
-1234567890.1M --> -12,,3456,,7890..1
-1234567890.12M --> -12,,3456,,7890..12
-1234567890.123M --> -12,,3456,,7890..123
-1234567890.1234M --> -12,,3456,,7890..1234
-1234567890.12347M --> -12,,3456,,7890..12347
-1234567890.123478M --> -12,,3456,,7890..123478
-1234567890.1234789M --> -12,,3456,,7890..1234789
-1234567890.12347890M --> -12,,3456,,7890..1234789
-1234567890.123478901M --> -12,,3456,,7890..123478901
-1234567890.1234789012M --> -12,,3456,,7890..1234789012
更新:我试着看一下
Decimal.ToString()
如何使用常规格式来显示需要显示的所有数字:
public override string ToString()
{
return Number.FormatDecimal(this, null, NumberFormatInfo.CurrentInfo);
}
除了Number.FormatDecimal
隐藏在某个地方之外:
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern string FormatDecimal(decimal value, string format, NumberFormatInfo info);
因此,这是一条死胡同。默认情况下,十进制方法使用CultureInfo.CurrentCulture作为用户会话,因此根据运行代码的用户而有所不同
ToString方法还接受各种重载中的IFormatProvider。这就是您需要提供特定于区域性的格式化程序的地方
例如,如果您传递fr CH的NumberFormat,则可以按照该区域性的要求格式化内容:
var culture = CultureInfo.CreateSpecificCulture("fr-CH");
Decimal value = -1234567890.1234789012M;
Console.WriteLine(value.ToString("##,#.###############", culture.NumberFormat));
将输出
-1'234'567'890.1234789012
编辑#3-使用自定义格式化程序重写。根据新更新的问题,这应该满足您的要求
编辑#4-获取所有输入,并运行以下操作:
public void TestOutput()
{
PrintValue(-1234567890M);
PrintValue(-1234567890.1M);
PrintValue(-1234567890.12M);
PrintValue(-1234567890.123M);
PrintValue(-1234567890.1234M);
PrintValue(-1234567890.12347M);
PrintValue(-1234567890.123478M);
PrintValue(-1234567890.1234789M);
PrintValue(-1234567890.12347890M);
PrintValue(-1234567890.123478901M);
PrintValue(-1234567890.1234789012M);
}
private static void PrintValue(decimal value)
{
var culture = CultureInfo.CreateSpecificCulture("qps-PLOC");
Console.WriteLine(value.ToString("##,#.###############", culture.NumberFormat));
}
提供与您提供的内容匹配的输出:
--12,,3456,,7890
--12,,3456,,7890..1
--12,,3456,,7890..12
--12,,3456,,7890..123
--12,,3456,,7890..1234
--12,,3456,,7890..12347
--12,,3456,,7890..123478
--12,,3456,,7890..1234789
--12,,3456,,7890..1234789
--12,,3456,,7890..123478901
--12,,3456,,7890..1234789012
正如Joshua所指出的,这只适用于某些地区
从外观上看,你需要从两个弊病中挑出较小的一个:知道数字的精度,或者为每种文化指定格式。我打赌知道你的数字的精确性可能会更容易。
在这种情况下,我的答案的前一个版本可能有用:
要显式控制要输出的小数位数,可以克隆区域性提供的数字格式并修改NumberDecimalDigits属性
var culture = CultureInfo.CreateSpecificCulture("fr-CH");
Decimal value = -1234567890.1234789012M;
NumberFormatInfo format = (NumberFormatInfo)culture.NumberFormat.Clone();
format.NumberDecimalDigits = 30;
Console.WriteLine(value.ToString("n", format));
这将产生:
-1'234'567'890.123478901200000000000000000000
格式化字符串时,需要包含区域性。可以使用并包含区域性作为第一个参数,也可以使用对象的方法并使用接受区域性的重载 以下代码生成预期的输出(除了gws FR,它找不到具有该字符串的区域性) 上述代码生成以下输出:
en-US -1,234,567,890.1234789012
ca-ES -1.234.567.890,1234789012
fr-CH -1'234'567'890.1234789012
ar-DZ 1,234,567,890.1234789012-
prs-AF 1.234.567.890,1234789012-
ps-AF 1،234،567،890,1234789012-
as-IN -1,23,45,67,890.1234789012
lo-LA (1234567,890.1234789012)
qps-PLOC --12,,3456,,7890..1234789012
如果您使用的是多线程系统,如ASP.Net,则可以更改线程的属性。更改线程的区域性将允许所有关联的ToString
和String.Format
调用使用该区域性
更新
因为你想显示所有的精度,你需要做一些工作。使用
NumberFormat.NumberDecimalDigits
将起作用,除非该值精度较低,否则该数字将以尾随零输出。如果需要确保显示的每个数字都没有任何附加值,则需要事先计算精度,并在将其转换为字符串之前进行设置。StackOverflow问题可以帮助您确定小数的精度。您可以指定自定义模式(该模式将适当地解析为特定于区域性的分组方法以及适当的分组和小数分隔符字符)。一个模式可以有。正模式总是相同的,但负模式取决于区域性,可以从NumberFormatInfo的属性中检索。由于您需要尽可能高的精度,因此需要在小数点后填写28位占位符;逗号强制分组
public static class DecimalFormatters
{
public static string ToStringNoTruncation(this Decimal n, IFormatProvider format)
{
NumberFormatInfo nfi = NumberFormatInfo.GetInstance(format);
string[] numberNegativePatterns = {
"(#,0.############################)", //0: (n)
"-#,0.############################", //1: -n
"- #,0.############################", //2: - n
"#,0.############################-", //3: n-
"#,0.############################ -"};//4: n -
var pattern = "#,0.############################;" + numberNegativePatterns[nfi.NumberNegativePattern];
return n.ToString(pattern, format);
}
public static string ToStringNoTruncation(this Decimal n)
{
return n.ToStringNoTruncation(CultureInfo.CurrentCulture);
}
}
样本输出
目前没有使用
negativeEnumberFormat
4(n-
)的区域设置,因此无法测试该案例。但没有理由认为它会失败。为什么不喜欢value.ToString(“n”)?@bang它只显示小数点后3位。我也喜欢General(value.ToString(“G”)
),只是它不显示数字分组。我喜欢一般(g)的小数和数字(n)的分组。它们一起将是不可阻挡的。这会将小数的数量截断为CultureInfo.NumberFormat.NumberDecimalDigits
,将小数的数量截断为CultureInfo.NumberFormat.NumberDecimalDigits
。不幸的是,使用自定义格式将打破某些区域性的负数。在您的示例中,lo-LA将在应该是(1234567890.1234789012)
时打印-1234567890.1234789012
。此外,对于ar DZ、prs AF和ps AF,负号位于左侧,而不是右侧。(这就是自定义格式的祸根)@Joshua…ack,对,所以,使用数字格式器和N的克隆可能是。。。更简单更准确?@WillHughes,我想你可以称之为更准确。处理文化是困难的,因此我倾向于尝试并依靠微软在.Net框架中正确处理文化。我还使用它来尝试保持一致性,因为我将调用相同的底层框架。我知道甚至微软以前也犯过错误,并在随后的补丁中修复了它。这可能需要另外一个问题,“如何知道十进制数字中的小数位数?”。这是一个完全不同的问题,是这个问题的复制品。这非常聪明,处理五种不同的负数模式。
en-US -1,234,567,890.1234789012
ca-ES -1.234.567.890,1234789012
fr-CH -1'234'567'890.1234789012
ar-DZ 1,234,567,890.1234789012-
prs-AF 1.234.567.890,1234789012-
ps-AF 1،234،567،890,1234789012-
as-IN -1,23,45,67,890.1234789012
lo-LA (1234567,890.1234789012)
qps-PLOC --12,,3456,,7890..1234789012
public static class DecimalFormatters
{
public static string ToStringNoTruncation(this Decimal n, IFormatProvider format)
{
NumberFormatInfo nfi = NumberFormatInfo.GetInstance(format);
string[] numberNegativePatterns = {
"(#,0.############################)", //0: (n)
"-#,0.############################", //1: -n
"- #,0.############################", //2: - n
"#,0.############################-", //3: n-
"#,0.############################ -"};//4: n -
var pattern = "#,0.############################;" + numberNegativePatterns[nfi.NumberNegativePattern];
return n.ToString(pattern, format);
}
public static string ToStringNoTruncation(this Decimal n)
{
return n.ToStringNoTruncation(CultureInfo.CurrentCulture);
}
}
Locale Output
======== ============================
en-US -1,234,567,890.1234789012
ca-ES -1.234.567.890,1234789012
hr-HR - 1.234.567.890,1234789012
gsw-FR -1 234 567 890,1234789012
fr-CH -1'234'567'890.1234789012
ar-DZ 1,234,567,890.1234789012-
prs-AF 1.234.567.890,1234789012-
ps-AF 1،234،567،890,1234789012-
as-IN -1,23,45,67,890.1234789012
lo-LA (1234567,890.1234789012)
qps-PLOC -12,,3456,,7890..1234789012