## How to fill in that number grouping member of NUMBERFMT

 Date: April 18, 2006 / year-entry #137 Tags: code Orig Link: https://blogs.msdn.microsoft.com/oldnewthing/20060418-11/?p=31493 Comments: 9 Summary: If you look at the NUMBERFMT structure, the way groups are expressed by the Grouping member do not match the value returned by LOCALE_SGROUPING: LOCALE_SGROUPING Grouping Sample Culture 3;0 3 1,234,567 United States 3;2;0 32 12,34,567 India 3 30 1234,567 (none I know of) LOCALE_SGROUPING expresses grouping as a series of semicolon-separated numbers, each expressing...

If you look at the `NUMBERFMT` structure, the way groups are expressed by the `Grouping` member do not match the value returned by `LOCALE_SGROUPING`:

LOCALE_
SGROUPING
Grouping Sample Culture
3;0 3 1,234,567 United States
3;2;0 32 12,34,567 India
3 30 1234,567 (none I know of)

`LOCALE_SGROUPING` expresses grouping as a series of semicolon-separated numbers, each expressing the number of digits in each group (least-significant group first). A trailing zero indicates that the last grouping should be repeated indefinitely. For example, "3;2;0" means "Group the three least significant digits, then in twos until you run out of digits." If there is no trailing ";0", then there are no commas past that point. For example, "3" means "Group the three least significant digits, then stop."

The `Grouping` member expresses the grouping rules differently. Each significant digit represents a group, with the most significant digit representing the least-significant group, with the units digit repeated indefinitely. For example, "32" means "make a group of three digits, then group by twos thereafter." To suppress the repetition, multiply by ten.

In other words, the two systems are basically the same, with the `Grouping` consisting of the `LOCALE_SGROUPING` string with the semicolons removed. Except that the meaning of the trailing zero is reversed, so if `LOCALE_SGROUPING` has a trailing zero, you have to remove it to get the `Grouping`, and if it lacks a trailing zero, then you have to add one to the `Grouping`.

It's kind of strange that the two systems differ, considering that they both came from the same NLS team! It's probably a case of parallel evolution, wherein the locale-string folks and the number-formatting folks came up with their respective systems independently.

Writing code to implement this conversion from `LOCALE_SGROUPING` to `Grouping` shouldn't be hard once you understand the algorithm, so I'll leave that as an exercise.

Fortunately, in real life you rarely have need to perform this conversion, for you can just pass the desired locale as the first parameter to the `GetNumberFormat` (or even better, `LOCALE_USER_DEFAULT`), pass a `NULL` pointer as the `lpNumberFormat`, and let NLS do all the work.

 Comments (9) Sorting It All Out says: Yesterday, when I talked about that post from Raymond about numeric grouping the locale sensitive way,… Daev says: Are there cultures that group decimal digits on the right-hand side of the decimal point as well? For instance:  3.141,592,635,5 Norman Diamond says: Tuesday, April 18, 2006 12:24 PM by Daev > Are there cultures that group decimal digits > on the right-hand side of the decimal point > as well? I wouldn’t call it a culture, but I saw that in some old ACM articles a few times.  It took a moment to get used to it. A bit more frequently I’ve seen spaces on the right-hand side of the decimal point. strik says: I find it puzzling that Windows insists on formatting for Germany like "1.234.567,89" (cf. http://blogs.msdn.com/oldnewthing/archive/2006/04/17/577483.aspx). Although this is the "official" way to do it, from experience, almost no-one uses this scheme when hand-writing. Rather, the dots are replaced by spaces (thus, "1 234 567,89". Much more interesting, some people really have problems if they got values with dots ("1.234" will be treated as 1 + 234/1000 instead of 1234 by many people I know). For example, I have yet to see any school teaching writing the dots for separating thousands; it is always a small space between the groups. Is there anyone out there who feels the same like me? Goran says: "1.234" will be treated as 1 + 234/1000 instead of 1234 by many people I know" Probably wasn’t the case before computers (with programs that don’t cater for different locales). Example: when I was in school, we wrote dates like this: 21. VI 2006 (june 21st, 2006). It’s rarely done now. I don’t think it’s even possible to do it with computers. Pitty, no? Mark Steward says: Goran: here you go!  This is in PHP, as the C++ equivalent is about 20 lines. Requires a font with the appropriate codepoints. Mark Steward says: Ahem.  I feel a bit dirty posting PHP here, even on a silly hack, so: DateTime Now = DateTime.Now; string Month = (Now.Month < 1 || Now.Month > 12) ? "MM" : "’" + (char)(0x215f + Now.Month) + "’"; string Date = Now.ToString("dd’.’ " + Month + " yyyy"); Not suggesting that anybody *does* this, of course… Although it suddenly occurs to me that you could get the same effect by putting the roman numerals as the "short name" for a month (perhaps the ELKs could help). me says: […] like "1.234.567,89" (cf. http://blogs.msdn.com/oldnewthing/archive/2006/04/17/577483.aspx). Although this is the "official" way to do it […] German standard DIN 5008:2001 clearly says to write numbers like "1 234 567,89". Only amounts of money should be written "1.234.567,89 EUR". Comments are closed.

*DISCLAIMER: I DO NOT OWN THIS CONTENT. If you are the owner and would like it removed, please contact me. The content herein is an archived reproduction of entries from Raymond Chen's "Old New Thing" Blog (most recent link is here). It may have slight formatting modifications for consistency and to improve readability.

WHY DID I DUPLICATE THIS CONTENT HERE? Let me first say this site has never had anything to sell and has never shown ads of any kind. I have nothing monetarily to gain by duplicating content here. Because I had made my own local copy of this content throughout the years, for ease of using tools like grep, I decided to put it online after I discovered some of the original content previously and publicly available, had disappeared approximately early to mid 2019. At the same time, I present the content in an easily accessible theme-agnostic way.

The information provided by Raymond's blog is, for all practical purposes, more authoritative on Windows Development than Microsoft's own MSDN documentation and should be considered supplemental reading to that documentation. The wealth of missing details provided by this blog that Microsoft could not or did not document about Windows over the years is vital enough, many would agree an online "backup" of these details is a necessary endeavor. Specifics include:
• A "redesign" after 2019 erased thousands of user's comments from previous years. As many have stated, the comments are nearly as important as the postings themselves. The archived copies of the postings contained here retain the original comments.
• The blog has changed domains many times and the urls have otherwise been under constant change since 2003. Even when proper redirection has been set up for those links, redirection only works for a limited period of time. For example, all of the internal blog links that were valid in early 2019, were broken by 2020 without proper redirection.
• The blog has been under constant re-design and re-theming since its inception. It is downright irritating to deal with a bogged-down site experience as the result of the latest visual themes designed for cell-phone browsers. As of this writing, it is cumbersome to navigate titles with only 10 entries per page. While it is nice that the official site has a search feature, searching using this index (with all titles on a single page) is much quicker (CTRL-F in most browsers).

<-- Back to Old New Thing Archive Index