How to specify a custom thousands separator in a format strings
Asked Answered
B

2

10

When I try the below code, I get the output 2 084 001. What could be wrong here? Isn't my format string supposed to override the current culture settings?

decimal v = 2084000.7621m;
System.Console.WriteLine(v.ToString("#,###,###"));
System.Console.ReadLine();

If I modify the code to use ToString("#,###,###", CultureInfo.InvariantCulture), I get the expected output, i.e. 2,084,001 but I cannot specify a format provider when I set the DataFormatString property on my data bound controls.

WARNING: When using an escaped literal group separator, as described below in the accepted and other answers, the literal character used is always output, even if it isn't needed, e.g. applying the format string #\,###\,### to a value of 324 results in an output value of ,,324.

Bewail answered 26/8, 2011 at 8:46 Comment(3)
What locale is the default one? Looks like the default one has the ThousandsSeparator set to a space.Liquor
@Oded, it is en-ZA, and it does have that set to a space. That is why I am using an explicit format string, to try and override the default.Bewail
I made the title more explicit for better recoverability, hope you agree.Arquebus
A
7

As far as I understand the Custom Numeric Format Strings, the , symbol is to place the group separator into the formatting (and not to specify which character to use). To make it an explicit symbol, you need to use the escape character \.

v.ToString(@"#\,###\,###")

Which has the disadvantage that the format string depends on the size of the number. In this case, you always get two commas in the resulting string, even if the number is smaller or higher.

To override the group separator, you need to specify your own NumberFormatInfo.

Got this test working:

decimal v = 2084000.7621m;

// clone the InvariantCulture to avoid specifying everything from scratch
var myNumberFormat = (NumberFormatInfo)CultureInfo.InvariantCulture.NumberFormat.Clone();
myNumberFormat.NumberGroupSeparator = "@";
myNumberFormat.NumberDecimalSeparator = "*";
Assert.AreEqual("2@084@000*7621", v.ToString("#,###,###.####", myNumberFormat));

It actually doesn't matter where and how many group separators you put into the format string. You could also make it: "#,#.####" with the exact same result. (Thats the advantage of using the group separator character, in contrast to the first solution).

Arquebus answered 26/8, 2011 at 9:13 Comment(1)
Ya, thanks. If only the documentation was a little more explicit about this. I have actually had the same problem many years ago and totally was not reminded by anything in the docs. It also seems most forum answers elsewhere on the web don't consider this.Bewail
W
1

Your problem is that the , character in your format string doesn't mean “insert a comma”; it actually means “insert the thousands separator for the current locale”, which happens to be a space in your default locale.

You will need to escape the comma by placing a backslash \ before it in your format string. You might need to use a double-backslash (or a verbatim string) to make the compiler accept the escape as you intended.

Walkthrough answered 26/8, 2011 at 9:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.