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

时间:2016-12-06 22:18:05

标签: c# vb.net string-formatting

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

  • 将显示的位数限制为最大值(例如16)。我能够使用number.ToString("G16")完成此任务。
  • 在数字上添加数字分组。我能够使用:number.ToString(String.Format("#,0.{0};-#,0.{0}", New String("#"c, 15)))
  • 来实现这一目标

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

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

Examples

如果使用一个字符串格式化无法实现所需的输出,我在下面添加了一个答案。如果您认为没有直接的方法来实现这一点(这是我原来的要求),请随意建议对该答案的任何优化/更改

很抱歉,如果我对任何人造成某种混淆。我只是认为可能有一个简单的字符串格式化来实现这一点,而且我仍然很想知道这是否真的。

5 个答案:

答案 0 :(得分:6)

经过大量搜索此问题。您无法使用单一格式执行此操作,因为您询问IF .. ELSE LOGIC不是单向格式化(对数字执行两次格式化)

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))))

<强> UPDATE1

根据您的更新,请使用以下

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正在使用新长度将结果再次转换为double。 注意:如果结果包含e,则会在解析后删除

  • ToString("#,#.#".PadRight(len, "#"), System.Globalization.CultureInfo.InvariantCulture)正在为生成的双重

  • 添加组数字

注意

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

如果你想减少数字,你必须在Substring

之后使用字符串函数,如LeftTostring("G1")

希望有所帮助

答案 1 :(得分:4)

我不知道以你想要的方式做到这一点的简单方法。

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

要明确的是,我并不是主张将这种方法作为一个好的解决方案 - 在一行中很难理解,但嘿,这对我来说是一项有趣的练习。

如果你想在一条可怕的线路上做这件事(c#):

SELECT 
    [Extent1].[Id] AS [Id], 
    [Extent1].[Number] AS [Number], 
    [Extent1].[CallTime] AS [CallTime], 
    [Extent1].[Duration] AS [Duration], 
    [Extent1].[Cost] AS [Cost]
    FROM  [dbo].[OperatorAs] AS [Extent1]
    INNER JOIN [dbo].[OperatorBs] AS [Extent2] 
        ON ([Extent1].[Number] = [Extent2].[Number]) 
        OR (([Extent1].[Number] IS NULL) AND ([Extent2].[Number] IS NULL))
否则分手一点;我采取的方法更清楚一点:

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('.')));

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

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

答案 2 :(得分:3)

如果不能使用一个字符串格式化,我将使用这个答案:

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计算器相同的输出)。

我只是认为可能有一个简单的字符串格式来实现这一目标,而且我仍然很想知道这是否属实。

答案 3 :(得分:0)

您可以使用String.format来应用多种格式。阅读Composite Formatting here

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

Tested in vb.net

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

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

对于第2部分,您只需使用N0为数千个地点添加逗号 - Standard Numeric Format Strings

答案 4 :(得分:0)

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