【问题标题】:Format decimal with commas, preserve trailing zeros用逗号格式化十进制,保留尾随零
【发布时间】:2012-06-14 16:49:10
【问题描述】:

我想将小数转换为字符串,用逗号作为千位分隔符,并保持与创建小数时相同的精度。 (将有 2-5 个有效数字)

        decimal d = 1234.4500M;

        //I'd like "1,234.4500"

        var notRight = d.ToString("###,###.#######");     //1,234.45
        var alsoNotRight = d.ToString("###,###.00000");;  //1,234.45000
        var notRightEither = d.ToString("N");    //1,234.45
        var notRightEither2 = d.ToString("G");   //1234.45000

如果不手动解析字符串,是否没有内置方法可以做到这一点?如果没有单一格式字符串,最简单的方法是什么?

【问题讨论】:

  • 我决定研究一下格式化是如何完成的。不幸的是,繁重的工作不是托管代码(不足为奇),看着Standard Numeric Format String,看起来只有"G"(默认)保留了空格。

标签: c# .net decimal string-formatting


【解决方案1】:

根据documentation,十进制数保留尾随零。如果您使用“G”说明符或根本不使用说明符,则可以显示它们。当您使用包含千位分隔符的说明符之一时,它们会丢失。

如果要在转换为字符串时指定尾随零的个数,可以通过在格式字符后添加a precision specifier(0到99位)来实现,如下所示:

decimal d=1234.45M;
var numberAsString=d.ToString("N4");

结果将是

 1,234.4500

更新: 您可以使用Decimal.GetBits 方法获取十进制位数,该方法返回数字的二进制表示。小数位数存储在第四个元素的第 16-23 位(第三个字节)中。

The fourth element of the returned array contains the scale factor and sign. It consists of the following parts:

...

Bits 16 to 23 must contain an exponent between 0 and 28, which indicates the power of 10 to divide the integer number.

使用所有数字获取字符串表示可以这样完成:

decimal d=1234.45000M;
var nums=Decimal.GetBits(d);
var decimals=BitConverter.GetBytes(nums[3])[2];
var formatStr="N"+decimals;
d.ToString(formatStr);

会产生

1,234.45000

【讨论】:

  • 您部分错误。尽管调试器会显示小数的值等于 1234.45,但保留了尾随的 0。试试下面的代码,例如:decimal d = 1234.4500M;Console.WriteLine(d); // outputs 1234.4500。
  • 您的答案仅涵盖数字恰好有 4 位小数的示例。我相信他试图保留原始的小数位数(2-5)。
  • 格式指定为一个数字除以 10 的幂。因此它可以区分存储 12345/100 或 1234500/10000。
  • 感谢 Guvante 的背景信息。我不知道!现在我知道为什么它总是尾随 0。
  • 更新显示如何从二进制表示中提取位数
【解决方案2】:

由于您计划使用可变的小数位数 (2-5),我认为您无法通过字符串格式实现。

这个解决方案不一定漂亮,但它可以完成工作。请注意,它会在过程中分配几个字符串(我相信是5个),所以它在大规模使用时可能表现不佳。您将保留小数位数,并在小数点前的部分中获得逗号分隔的组。

public static string FormatDecimal(decimal d)
{
    return d.ToString("N0") + // Format portion before decimal
           "." + 
           d.ToString().Split('.')[1];  // Retain number of decimal places
}

【讨论】:

  • 可以从十进制的二进制表示中提取位数,构造一个位数正确的格式字符串
  • 您还使用了特定于文化的分隔符,这意味着如果在法国、德国、西班牙、意大利、希腊、南非等使用“,”表示小数的文化中使用您的代码将会中断
  • 我喜欢它——它很容易一眼就能理解代码。虽然如果值没有小数部分(如 5M),你可能会得到一个超出范围的索引
  • 非常正确。我试图为解决方案提出至少一个起点。它绝对不是全球化的,也不处理没有小数的数字(OP 的用例是 2-5 位小数)。看起来 Panagiotis 已经着手并提出了一个完整的解决方案,所以我不会再更新了。
猜你喜欢
  • 1970-01-01
  • 2016-11-13
  • 2013-08-20
  • 2012-07-25
  • 1970-01-01
  • 1970-01-01
  • 2011-02-12
  • 1970-01-01
  • 2021-06-20
相关资源
最近更新 更多