.NET 通用数字格式与千位分隔符

Posted

技术标签:

【中文标题】.NET 通用数字格式与千位分隔符【英文标题】:.NET General Number Formatting with Thousands Separator 【发布时间】:2015-04-13 07:01:06 【问题描述】:

.NET 中是否可以使用最紧凑的数字格式,例如 "G"eneral Number formatting,带有额外的千位分隔符

我不能使用下面的

String.Format("0:#,###.###",32445.324777M)

因为我得到了"32,445.325",而我想要的结果应该是"32.445,325777"。 Is 也应该与小数部分中任意数量的有效数字一起使用。

PS:我只需要decimals。

【问题讨论】:

您正在解决您的问题的 2 个问题:1) 使用小数分隔符切换组分隔符(使用适当的文化)和 2) 不限制小数位数,不明确使用 #。 .. 【参考方案1】:

这就是格式化文化的用武之地。您需要获得一个符合您要求的格式说明符。您拥有的默认值通常是当前文化、UI 文化或不变文化。您得到的结果表明您正在使用美国文化。

如果您想要输出数字的特定文化,请使用它。如果没有,您可以创建自己的:

var nfi = 
  new NumberFormatInfo 
   
    NumberDecimalSeparator = ",", 
    NumberGroupSeparator = "." 
  ;

var ci = 
  new CultureInfo(CultureInfo.InvariantCulture.LCID)  NumberFormat = nfi ;

return string.Format(ci, "0:#,###.########", 32445.324777M)

如果您还想获得最紧凑的号码,则必须使用自己的代码。最简单的方法是尝试两者,并返回较小的结果字符串。

如果您愿意,您仍然可以使用 string.Format 语法 - 您可以编写自己的 ICustomFormatter 来处理它:

void Main()

    var number = 32445.324777M;

    string.Format(new MyNumberFormatter(),  "0:MyG", number).Dump();


class MyNumberFormatter : IFormatProvider, ICustomFormatter

  public object GetFormat(Type type)
  
    return this;
  

  public string Format(string fmt, object arg, IFormatProvider formatProvider)
  
    if (fmt != "MyG" || !(arg is decimal)) return string.Format(CultureInfo.CurrentCulture, "0:" + fmt + "", arg);

    return "Hi";
  

这个实现有点hacky,当然,我相信你能找到更好的例子。但它确实有效。在Format 方法中,您可以选择更适合给定数字的格式,或者甚至只是尝试执行通常的ToString("G", CultureInfo.InvariantCulture) 并将小数分隔符添加到该字符串中。无论你的船漂浮什么:)

【讨论】:

【参考方案2】:

来自.NET documentation

“#”自定义格式说明符用作数字占位符符号。 如果正在格式化的值的位置有一个数字 “#”符号出现在格式字符串中,该数字被复制到 结果字符串。

否则,没有任何内容存储在该位置 结果字符串。请注意,此说明符从不显示零 不是有效数字,即使零是唯一的数字 细绳。只有当它是有效数字时才会显示零 正在显示的数字。

“##”格式字符串导致 要四舍五入到小数点前最接近的数字的值,其中 始终使用从零四舍五入的方法。例如,格式化 34.5 使用 "##" 将导致值 35。

无法使用默认格式设置未指定数量的小数位数。因此,如果需要,您应该考虑编写自己的实现。

关于小数点和千位分隔符,这取决于您的系统设置,但您可以使用 @Luaan 在他的回答中描述的不同文化来覆盖它们。

你也应该看看this answer。

【讨论】:

【参考方案3】:

如果您想要完全控制,请创建 yoru 自己的格式化程序,如下所示。请参阅大小写“U”以了解您的格式。

public class CustomerFormatter : IFormatProvider, ICustomFormatter

    public object GetFormat(Type formatType)
    
        if (formatType == typeof(ICustomFormatter))
            return this;
        else
            return null;
    

    public string Format(string format,
                          object arg,
                          IFormatProvider formatProvider)
    
        if (!this.Equals(formatProvider))
        
            return null;
        
        else
        
            // generic formatter if no formater specified
            if (String.IsNullOrEmpty(format))
                format = "G";

            // not a decimal type object
            if (!(arg is decimal))
                return null;

            // get value
            decimal val = (decimal)arg;

            // convert value into generic culture string for control of format
            string valueString = val.ToString();

            // get string in required format type
            format = format.ToUpper();
            switch (format)
            
                // our user format
                case "U":

                    // get decimals
                    string decimals = val.ToString("G", CultureInfo.InvariantCulture);
                    decimals = decimals.Substring(decimals.IndexOf('.') + 1);

                    // get current culture info
                    NumberFormatInfo nfi = new CultureInfo(CultureInfo.CurrentCulture.Name).NumberFormat;

                    // set our separators
                    nfi.NumberGroupSeparator = ",";
                    nfi.NumberDecimalSeparator = ".";

                    // set numebr of decimals
                    nfi.NumberDecimalDigits = decimals.Length;

                    // convert value to our format
                    valueString = val.ToString("N", nfi);
                    break;
                default:
                    break;
            

            return valueString;
        
    


class Program

    static void Main(string[] args)
    
        decimal dec = 32445.324777M;
        Console.WriteLine(String.Format(new CustomerFormatter(), "0", dec));
        Console.WriteLine(String.Format(new CustomerFormatter(), "0:G", dec));
        Console.WriteLine(String.Format(new CustomerFormatter(), "0:U", dec));
        Console.WriteLine(String.Format(new CustomerFormatter(), "0:T", dec));

        Console.ReadLine();
    

【讨论】:

以上是关于.NET 通用数字格式与千位分隔符的主要内容,如果未能解决你的问题,请参考以下文章

asp.net mvc 设置数字格式默认十进制千位分隔符

检测 VB.Net 中数字的文化,即小数点/千位分隔符的句点或逗号

如何在 Dart 中将数字格式化为千位分隔符

数字格式,去掉千位分隔符

如何格式化数字来定义千位分隔符?

带有千位分隔符和小数的数字格式(如有必要)