考虑一个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
我想 (视文化)是:
en-US -1,234,567,890.1234789012
ca-ES -1.234.567.890,1234789012
gsw-FR -1 234 567 890,1234789012 (12/1/2012: fixed gws-FR to gsw-FR)
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) (some debate if numbers should be "1,234,567,890")
qps-PLOC 12,,3456,,7890..1234789012
我如何能转换成Decimal
为一个字符串,用数字分组?
更新 :一些更期望的输出,使用我目前的文化:
-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);
所以这是一个死胡同。
Answer 1:
您可以指定一个自定义模式(该模式将妥善解决,以分组的文化具体方法及相应的分组和小数点分隔符)。 图案可以具有正,负和零的部分 。 正模式始终是相同的,但否定模式依赖于文化,可以从的NumberFormatInfo的检索NumberNegativePattern财产。 既然你要尽可能精确可能,你需要填写到小数点后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);
}
}
示例输出
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
目前,使用没有语言环境NegativeNumberFormat
4( n -
所以这种情况下,不能进行测试。 但是,我们没有理由认为它会失败。
Answer 2:
该ToString
在默认情况下,小数方法使用的用户会话的CultureInfo.CurrentCulture,从而改变基于谁运行代码。
ToString方法还允许在各种过载的的IFormatProvider。 这就是你需要提供特定的文化格式化程序。
举例来说,如果你通过的NumberFormat为FR-CH,您可以作为文化期待格式化的东西:
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
正如约书亚指出,这仅适用于某些地区。
从它那么看起来,你需要选择两两害相权较小:了解你的号码的精度,或指定格式为每一种文化。 我打赌知道你的号码的精确度可能会更容易。 在这种情况下,我的答案以前的版本可能是有用的:
要明确控制小数输出的数量,你可以克隆由文化所提供的数字格式,并修改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
Answer 3:
您需要包括文化格式化您的字符串时。 您可以使用的String.Format和包括文化作为第一个参数或使用对象的ToString方法和使用,需要一个文化的过载。
下面的代码产生预期的输出(除GWS-FR,它无法找到该字符串的文化)。
namespace CultureFormatting {
using System;
using System.Globalization;
class Program {
public static void Main() {
Decimal value = -1234567890.1234789012M;
Print("en-US", value);
Print("ca-ES", value);
//print("gws-FR", value);
Print("fr-CH", value);
Print("ar-DZ", value);
Print("prs-AF", value);
Print("ps-AF", value);
Print("as-IN", value);
Print("lo-LA", value);
Print("qps-PLOC", value);
}
static void Print(string cultureName, Decimal value) {
CultureInfo cultureInfo = new CultureInfo(cultureName);
cultureInfo.NumberFormat.NumberDecimalDigits = 10;
// Or, you could replace the {1:N} with {1:N10} to do the same
// for just this string format call.
string result =
String.Format(cultureInfo, "{0,-8} {1:N}", cultureName, value);
Console.WriteLine(result);
}
}
}
上面的代码产生以下输出:
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工作,你可以改变线程的的CurrentCulture属性。 更改线程的文化将允许所有相关的ToString
和String.Format
调用使用文化。
更新
既然你想显示所有的精密你将不得不做一些工作。 使用NumberFormat.NumberDecimalDigits
会工作,但如果该值具有精度要求不高,数量将尾随零输出。 如果你需要确保你没有任何额外显示每一个数字,你需要事先计算精度,并设置将其转换为字符串之前。 在StackOverflow的问题计算System.Decimal精度和规模可能能够帮助您确定小数的精度。
文章来源: Decimal to string with thousand's separators?