十进制字符串千的分隔符?(Decimal to string with thousand's

2019-06-26 04:01发布

考虑一个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属性。 更改线程的文化将允许所有相关的ToStringString.Format调用使用文化。

更新

既然你想显示所有的精密你将不得不做一些工作。 使用NumberFormat.NumberDecimalDigits会工作,但如果该值具有精度要求不高,数量将尾随零输出。 如果你需要确保你没有任何额外显示每一个数字,你需要事先计算精度,并设置将其转换为字符串之前。 在StackOverflow的问题计算System.Decimal精度和规模可能能够帮助您确定小数的精度。



文章来源: Decimal to string with thousand's separators?