Why some cultures round currency decimals by default?
Asked Answered
H

2

6

I have noted that when using the framework function string.Format to format currency values, in some cultures this function rounds the decimals by default. For example, when working with Malaysian ringgits:

CultureInfo culture = new CultureInfo("ms-MY");
someLabel.Content = string.Format(culture,"{0:C}", 1.64m);

Outputs: RM2

However when working with other currencies, like USD, euros or others, you get the original value, for example:

CultureInfo culture = new CultureInfo("sv-SE");
someLabel.Content = string.Format(culture,"{0:C}", 1.64m);

Outputs: 1.64kr

I know that I can specify the number of decimals in the CultureInfo class, but the question is, why this happens with some currencies but not with others? It is expected that some currencies are rounded by default?

Hierocracy answered 17/8, 2015 at 8:31 Comment(0)
E
11

From The Currency "C" Format Specifier

If the precision specifier is omitted, the default precision is defined by the CurrencyDecimalDigits property.

And this ms-MY culture has 0 as a CurrencyDecimalDigits property. That's why it doesn't have any decimal places in the result.

enter image description here

As a solution, you can use precision specifier as;

CultureInfo culture = new CultureInfo("ms-MY");
someLabel.Content = string.Format(culture,"{0:C2}", 1.64m); // RM1.64

Why some currencies are rounded (or they have this property set to 0, if you prefer), but not others. Is there some rule for that?

Honestly, I don't know. But I made some research and here what I found;

Malaysia uses ringgit as a currency. It is divided into 100 sen. And with it's third series, there were be only 4 coins as; 5 sen, 10 sen, 20 sen, 50 sen.

With previous (second) series;

As of 1 April 2008, a rounding mechanism of prices to the nearest 5 sen, applied to the total bill only, is in force, which was first announced in 2007 by Bank Negara Malaysia, in an attempt to render the 1 sen coin irrelevant.

Article: http://www.thestar.com.my/story/?file=%2f2007%2f11%2f14%2fnation%2f19460993&sec=nation&focus=1

How it works

This image kind of useful about telling you can't divide a RM by 100 because it will not be meaningful. By the way, I have to say this 0 value does not match with ISO 4217 which specifies currency designators. From Active Codes section, you can see this MYR has 2 decimal digits in this standard.

This XML file from currency-iso.org says this as well;

<CcyNtry>
  <CtryNm>MALAYSIA</CtryNm>
  <CcyNm>Malaysian Ringgit</CcyNm>
  <Ccy>MYR</Ccy>
  <CcyNbr>458</CcyNbr>
  <CcyMnrUnts>2</CcyMnrUnts>
</CcyNtry>

Also from Contemporary non-decimal currencies section in Non-decimal currency page;

Today only two countries in the world use non-decimal currencies. Both are in Africa. These are Mauritania (1 ouguiya = 5 khoums) and Madagascar (1 ariary = 5 iraimbilanja). However these are only theoretically non-decimal, as in both cases the value of the main unit is so low that the sub-unit is too small to be of any practical use and coins of the sub-unit are no longer used

Check the other sections of this page by the way, there are really useful information about that.

This is kind of complicated in my opinion. I also connected to .NET Team as well. I will update this answer when I get feedback from them.

UPDATE 18/08/2015

As Tarek mentioned, this CurrencyDecimalDigits property of this my-MY culture changed as 2 in Windows 10.

And Shawn Steele (Windows and .NET Framework globalization API expert) suggests as;

Probably formatting currencies using Windows.Globalization and doing it by currency might be a better idea.

UPDATE 21/02/2016

Looks like this happens on Windows Server 2012 R2 again. I connected to .NET Team about this and they respond as we can use Locale Builder to create a new custom culture or edit an existing culture to change this ICURRDIGITS settings as 2.

Etesian answered 17/8, 2015 at 8:37 Comment(8)
Ok, but that does not answers my question. Why some currencies are rounded (or they have this property set to 0, if you prefer), but not others. Is there some rule for that? I'm asking this because it is not very practical to have to check each possible currency you may end working withHierocracy
@AlejandroMartin - I expect it's because the minor currency unit "sen" (cent: 100 sen = RM1) has such a low value that it's no longer used. The same is true of JPY.Maeganmaelstrom
@AlejandroMartin: The number of digits to display depends on the currency. ISO 4217 contains a list of currencies where you can see the number of decimal digits to display (0-4). In .NET a CultureInfo is associated with a currency and also a number of decimal digits to display by default. For some reason the ms-MY culture sets the decimal digits to 0 and not to 2 which is the correct number according to ISO 4217 but I have no idea why.Selfwill
@MartinLiversage Exactly. I was investigating that for an hour. Also connected to .NET Team about that. Strongly suspect this CurrencyDecimalDigits property does not follow ISO 4217 rules or at least, not updated.Valery
@AlejandroMartin I added some information about that. Check it out.Valery
@SonerGönül Awesome investigationHierocracy
Thanks for the comprehensive answer, I spent an hour scratching my head over this when client says I am rounding their prices. The numbers are fine on my Windows 10 dev machine, but on Windows Server 2012 they got rounded to 0 decimal places. Your answer seems pretty well researched but I believe this is nothing more than just a bug in Microsoft culture information.Jeffereyjefferies
@RosdiKasim You have a point, this CurrencyDecimalDigits property of ms-MY culture is still 0 in Windows Server 2012 R2. I mailed to .NET Team about this. I will inform you and update my answer when they return to me.Valery
N
0

The number of decimals digits is controlled by NumberFormatInfo.CurrencyDecimalDigits (https://msdn.microsoft.com/en-us/library/system.globalization.numberformatinfo.currencydecimaldigits(v=vs.110).aspx)

in ms-MY culture, this CurrencyDecimalDigits is zero by default, which cause the number to be rounded. in other culture like sv-SE, CurrencyDecimalDigits is 2 which show 1,64.

You can control that either by specifying {0:C2} or you can change the value on NumberFormatInfo like:

CultureInfo culture = new CultureInfo("ms-MY");
NumberFormatInfo nfi = (NumberFormatInfo)culture.NumberFormat.Clone();
nfi.CurrencyDecimalDigits = 2;
content = string.Format(nfi, "{0:C}", 1.64m);

if you think CurrencyDecimalDigits for ms-MY shouldn't be zero we can pass this feedback to Windows team as they control the culture data on Windows.

Thanks

Nonlinearity answered 17/8, 2015 at 18:16 Comment(2)
To mention, Windows 10 has updated the culture information for ms-MY to have CurrencyDecimalDigits is 2. so the original posted code should produce the desired result without any change (which is RM1.64)Nonlinearity
On Windows Server 2012 R2 the digit is still 0 (as of today). The Windows Server has .NET 4.6 installed and has the latest updates. I believe this is a bug because the same code behaves differently on different OS.Jeffereyjefferies

© 2022 - 2024 — McMap. All rights reserved.