简体   繁体   English

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

[英]Format decimal number with digit grouping and limit the number of digits

Basically I'm trying to perform number formatting in the exact same way as the Windows calculator does.基本上,我试图以与 Windows 计算器完全相同的方式执行数字格式化。 Hence, my requirements are:因此,我的要求是:

  • Limit the number of displayed digits to a maximum (eg 16).将显示位数限制为最大值(例如 16)。 I was able to accomplish that using number.ToString("G16") .我能够使用number.ToString("G16")来完成。
  • Add digit grouping to the number.将数字分组添加到号码。 I was able to accomplish that using: number.ToString(String.Format("#,0.{0};-#,0.{0}", New String("#"c, 15)))我能够使用: number.ToString(String.Format("#,0.{0};-#,0.{0}", New String("#"c, 15)))

Any ideas on how to combine these together to get the same behavior as Windows calculator?关于如何将这些组合在一起以获得与 Windows 计算器相同的行为的任何想法?


Some examples with the desired output:具有所需输出的一些示例:

例子


I added an answer below which I would be using if the desired output can't be achieved using one string formatting.我在下面添加了一个答案,如果使用一种字符串格式无法实现所需的输出,我将使用该答案。 Feel free to suggest any optimizations/changes to that answer if you believe no direct way to achieve this (which is my original requirement)如果您认为没有直接的方法可以实现这一点,请随意建议对该答案进行任何优化/更改(这是我最初的要求)

Sorry if I caused some kind of confusion to anyone.对不起,如果我给任何人造成了某种混乱。 I just thought that there might be a simple one string formatting to achieve this and I was -and still am- curious to find out if that's true.我只是认为可能有一个简单的单字符串格式来实现这一点,我一直 - 而且仍然 - 很想知道这是否属实。

After a lot of search on this issue.在对这个问题进行了大量搜索之后。 You cannot perform this with a single format because you are asking about an IF .. ELSE LOGIC not for a one-way formatting ( performing two formatting on a number )您不能使用单一格式执行此操作,因为您询问的是IF .. ELSE LOGIC 不是用于单向格式(对数字执行两种格式

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

    ... do something

ELSE

    ... group digits

So you have to use an IF to achieve this所以你必须使用IF来实现这一点

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

Update1更新1

Based on your update use the following根据您的更新使用以下内容

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) is formatting dbl to a fixed length = len dbl.ToString("G" &len)dbl格式化为固定长度 = len

  • Double.parse is converting the result again to double with the new length. Double.parse正在将结果再次转换为具有新长度的 double。 Note: if th result contains e it will be removed after parse注意:如果结果包含e它将在解析后被删除

  • ToString("#,#.#".PadRight(len, "#"), System.Globalization.CultureInfo.InvariantCulture) is adding Group digits to the resulted double ToString("#,#.#".PadRight(len, "#"), System.Globalization.CultureInfo.InvariantCulture)正在将组数字添加到结果双ToString("#,#.#".PadRight(len, "#"), System.Globalization.CultureInfo.InvariantCulture)

Note笔记

When providing length ("G15") it will round the number to it.当提供长度("G15")它会将数字四舍五入。 It may reduce length from decimal part but it doesn't from the integers it will round the number to the specified length.它可能会减少小数部分的长度,但不会减少整数,它将数字四舍五入到指定的长度。 Ie 1734.Tostring("G1") will returns 2000 but not 2 / 1734.Tostring("G2") will returns 1700 but not 171734.Tostring("G1")将返回2000但不是2 / 1734.Tostring("G2")将返回1700但不是17

If you want to reduce numbers you have to use String Functions like Substring And Left after the Tostring("G1")如果你想减少数字,你必须在Tostring("G1")之后使用像SubstringLeft这样的字符串函数

Hope it helps希望能帮助到你

I don't know an easy way to do that in the way you are looking for.我不知道以您正在寻找的方式做到这一点的简单方法。

But being a curious sort of fellow I did wonder how it could be achieved using only string methods.但是作为一个好奇的家伙,我确实想知道如何仅使用字符串方法来实现。

To be clear, I'm not advocating this approach as a good solution - it's rather hard to understand in one line, but hey, an interesting exercise for me.需要明确的是,我并不是在提倡将这种方法作为一个好的解决方案 - 用一句话很难理解,但是,嘿,对我来说是一个有趣的练习。

If you felt like doing it in one horrendous line (c#):如果你想在一个可怕的行 (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('.')));

Otherwise broken up a little;否则就分手一点; it's a little clearer what approach I'm taking:我采取的方法更清楚一点:

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

I'm adding a decimal point to the end of the string so that there is at least one decimal point in the number (string).我在字符串的末尾添加了一个小数点,以便数字(字符串)中至少有一个小数点。 Then grab the text to the left of the first decimal point and concatenate it with any text from the first and to the left of the last decimal point.然后抓取第一个小数点左侧的文本,并将其与第一个和最后一个小数点左侧的任何文本连接起来。

If there was no decimal point in the original string then these two points are the same - the substring 0 characters long - removing the added decimal point.如果原始字符串中没有小数点,那么这两个点是相同的 - 子字符串长度为 0 个字符 - 删除添加的小数点。

This is an answer I would be using if this can't be done using one string formatting:如果使用一种字符串格式无法做到这一点,这是我将使用的答案:

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

This will -AFAICT- produce my desired output (the same output of Windows calculator).这将 -AFAICT- 产生我想要的输出(与 Windows 计算器的输出相同)。

I just thought that there might be a simple one string formatting to achieve this and I was -and still am- curious to find out if that's true.我只是认为可能有一个简单的单字符串格式来实现这一点,我一直 - 而且仍然 - 很想知道这是否属实。

You can use String.format to apply multiple formats.您可以使用String.format来应用多种格式。 Read about Composite Formatting here : 在此处阅读有关复合格式的信息

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

Tested in vb.net在 vb.net 中测试

You can drop the zeros or use your formatting, but the original question was about applying multiple formats.您可以删除零或使用您的格式,但最初的问题是关于应用多种格式。

You might need to convert the number to long while formatting, test it out at your end.可能需要在格式化时将数字转换为 long,最后进行测试。

For part 2, you can just use N0 to add the commas for thousands places - Standard Numeric Format Strings对于第 2 部分,您可以使用N0为数千个位置添加逗号 - 标准数字格式字符串

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM