用数字分组格式化十进制数并限制位数

Format decimal number with digit grouping and limit the number of digits

基本上,我正在尝试以与 Windows 计算器完全相同的方式执行数字格式设置。因此,我的要求是:

关于如何将这些组合在一起以获得与 Windows 计算器相同的行为的任何想法?


一些具有所需输出的示例:


我在下面添加了一个答案,如果使用一种字符串格式无法实现所需的输出,我将使用该答案。如果您认为没有直接的方法来实现这一点(这是我最初的要求),请随时向该答案提出任何 optimizations/changes

对不起,如果我给任何人造成了某种混乱。我只是认为可能有一种简单的单字符串格式来实现这一点,我当时 - 并且仍然 - 很好奇,想知道这是不是真的。

您可以使用 String.format to apply multiple formats. Read about Composite Formatting here :

String.Format("{0:N0}", Clng(number.ToString("G16")))

Tested in vb.net

您可以删除零或使用您的格式,但最初的问题是关于应用多种格式。

可能需要在格式化时将数字转换为 long,最后测试一下。

对于第 2 部分,您可以只使用 N0 为千位添加逗号 - Standard Numeric Format Strings

经过对这个问题的大量搜索。您不能使用单一格式执行此操作,因为您询问的是 IF .. ELSE 逻辑而不是单向格式(对数字执行两种格式

IF d.ToString("G16") contains scientific notation

    ... do something

ELSE

    ... group digits

所以你必须使用 IF 来实现这个

Str = If( num.ToString("G15").Contains("e"), num.ToString("G15"), num.ToString(String.Format("#,0.{0};-#,0.{0}", New String("#"c, 15))))

更新1

根据您的更新使用以下内容

Public Function FormatDouble(ByVal dbl As Double, ByVal len As Integer) As String

    Return Double.Parse(dbl.ToString("G" & len)).ToString("#,#.#".PadRight(len, "#"), System.Globalization.CultureInfo.InvariantCulture)

End Function
  • dbl.ToString("G" &len) 正在将 dbl 格式化为固定长度 = len

  • Double.parse 再次将结果转换为新长度的两倍。 注意:如果结果包含e,它将在解析后被删除

  • ToString("#,#.#".PadRight(len, "#"), System.Globalization.CultureInfo.InvariantCulture) 正在将组数字添加到结果 double

备注

提供长度 ("G15") 时,它会将数字四舍五入。它可能会减少小数部分的长度,但不会减少整数部分的长度,它会将数字四舍五入到指定的长度。 IE。 1734.Tostring("G1") 会 returns 2000 但不会 2 / 1734.Tostring("G2") 会 returns 1700 但不会 17

如果你想减少数字,你必须使用 字符串函数,比如 SubstringLeftTostring("G1") [=31= 之后]

希望对您有所帮助

如果使用一种字符串格式无法完成此操作,我将使用以下答案:

Private Function RoundAndGroup(num As Decimal) As String
    ' This will round the input to limit the number of digit to 16.
    Dim rounded As String = num.ToString("G16")
    ' Take only the whole part of the number to group and then combine with the rounded part.
    Dim whole As String = rounded.Split(".")(0)
    ' Group the whole part (if any) and combine with the rounded part (also if any).
    Dim grouped As String = Long.Parse(whole).ToString("N0") & ' Thanks to KScandrett's comment
                            rounded.Substring(whole.Length)
    Return grouped
End Function

这将 -AFAICT- 产生我想要的输出(Windows 计算器的相同输出)。

我只是认为可能有一种简单的单字符串格式来实现这一点,我当时 - 并且仍然 - 很好奇,想知道这是不是真的。

我不知道以您正在寻找的方式做到这一点的简单方法。

但作为一个好奇的家伙,我确实想知道如何只使用字符串方法来实现它。

需要说明的是,我并不是在提倡将这种方法作为一个好的解决方案 - 它很难用一句话来理解,但是嘿,这对我来说是一个有趣的练习。

如果您想在一个可怕的行 (c#) 中完成它:

var num1 = 123123123.456456456;  // result: 123,123,123.4564565
//var num1 = 123123123456456456.78;  // result: 1.231231234564565E+17
//var num1 = 123123123456; // result: 1,231,231,234,564,564
//var num1 = 1231231; // result: 1,231,231

Console.WriteLine(long.Parse((num1.ToString("G16") + ".").Substring(0, (num1.ToString("G16") + ".").IndexOf('.'))).ToString("N0") + (num1.ToString("G16") + ".").Substring((num1.ToString("G16") + ".").IndexOf('.'), (num1.ToString("G16") + ".").LastIndexOf('.')- (num1.ToString("G16") + ".").IndexOf('.')));

不然有点散了;我正在采取的方法更清楚一些:

var num1 = 123123123.456456456;
var num1a = num1.ToString("G16") + "."; 

Console.WriteLine(long.Parse(num1a.Substring(0, num1a.IndexOf('.'))).ToString("N0") + num1a.Substring(num1a.IndexOf('.'), num1a.LastIndexOf('.')- num1a.IndexOf('.')));

我在字符串的末尾添加了一个小数点,以便数字(字符串)中至少有一个小数点。然后抓取第一个小数点左边的文本,并将它与从第一个小数点到最后一个小数点左边的任何文本连接起来。

如果原始字符串中没有小数点那么这两点是相同的-子字符串长0个字符-去掉添加的小数点。

static formatDecimal(decimal decimalVar, int size)
{
    return decimalVar.ToString("#.##").PadLeft(size, '0'); 
}