【问题标题】:Why some cultures round currency decimals by default?为什么有些文化默认舍入货币小数?
【发布时间】:2015-08-17 08:31:34
【问题描述】:

我注意到,当使用框架函数string.Format 格式化货币值时,在某些文化中,此函数默认舍入小数。例如,使用马来西亚林吉特时:

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

输出:RM2

但是,当使用其他货币(例如美元、欧元或其他货币)时,您会得到原始值,例如:

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

输出:1.64kr

我知道我可以在 CultureInfo 类中指定小数位数,但问题是,为什么某些货币会发生这种情况,而其他货币则不会?预计部分币种会默认四舍五入?

【问题讨论】:

    标签: c# .net culture string.format


    【解决方案1】:

    来自The Currency "C" Format Specifier

    如果省略精度说明符,则默认精度为 由CurrencyDecimalDigits 属性定义。

    而这种ms-MY 文化具有0 作为CurrencyDecimalDigits 属性。这就是结果中没有小数位的原因。

    作为一种解决方案,您可以使用精度说明符 as;

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

    为什么有些货币是四舍五入的(或者他们将此属性设置为 0, 如果您愿意),但不是其他人。有什么规定吗?

    老实说,我不知道。但我做了一些研究,在这里我发现了什么;

    马来西亚使用ringgit 作为货币。它分为 100 仙。加上third series,只有4个硬币; 5仙,10仙,20仙,50仙。

    previous (second) series;

    截至 2008 年 4 月 1 日,rounding mechanism 的价格精确到 5 sen,仅适用于总法案,生效,这是第一个 马来西亚国家银行于 2007 年宣布,试图使 1 仙硬币无关紧要。

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

    这张图片告诉你不能将 RM 除以 100,因为它没有意义。顺便说一句,我不得不说这个0 值与指定货币标识符的ISO 4217 不匹配。从Active Codes section,你可以看到这个MYR在这个标准中有2十进制数字。

    这个XML file from currency-iso.org也这么说;

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

    也来自非十进制货币页面中的Contemporary non-decimal currencies 部分;

    如今,世界上只有两个国家使用非十进制货币。两个都 在非洲。这些是毛里塔尼亚(1 ouguiya = 5 khoums)和 马达加斯加(1 ariary = 5 iraimbilanja)。 但这些只是 理论上非十进制,因为在这两种情况下,主要单位的价值 太低以至于子单元太小而无法实际使用 和子单位的硬币不再使用

    顺便看看这个页面的其他部分,那里有非常有用的信息。

    在我看来,这有点复杂。我也连接到 .NET Team。当我收到他们的反馈时,我会更新这个答案。

    2015 年 8 月 18 日更新

    作为 Tarek mentioned,此 my-MY 文化的 CurrencyDecimalDigits 属性在 Windows 10 中更改为 2

    Shawn Steele(Windows 和 .NET Framework 全球化 API 专家)建议为;

    可能使用Windows.Globalization 和 用货币来做可能是一个更好的主意。

    2016 年 2 月 21 日更新

    看起来这种情况再次发生在 Windows Server 2012 R2 上。我就此与 .NET 团队联系,他们做出回应,因为我们可以使用 Locale Builder 创建新的自定义文化或编辑现有文化以将此 ICURRDIGITS 设置更改为 2

    【讨论】:

    • 好的,但这并不能回答我的问题。为什么有些货币是四舍五入的(或者如果您愿意,他们将此属性设置为 0),而其他货币则不是。有什么规则吗?我之所以这样问,是因为必须检查您可能最终使用的每种可能的货币并不是很实际
    • @AlejandroMartin:显示的位数取决于货币。 ISO 4217 包含一个货币列表,您可以在其中查看要显示的小数位数 (0-4)。在 .NET 中,CultureInfo 与货币以及默认显示的小数位数相关联。出于某种原因,ms-MY 文化将十进制数字设置为 0 而不是 2,根据 ISO 4217 这是正确的数字,但我不知道为什么。
    • @MartinLiversage 完全正确。我正在调查那个一个小时。还连接到 .NET 团队。强烈怀疑这个 CurrencyDecimalDigits 属性不遵循 ISO 4217 规则,或者至少没有更新。
    • @SonerGönül 很棒的调查
    • 感谢您的全面回答,当客户说我正在四舍五入他们的价格时,我花了一个小时摸索这个问题。这些数字在我的 Windows 10 开发机器上很好,但在 Windows Server 2012 上,它们四舍五入到小数点后 0 位。您的答案似乎经过充分研究,但我相信这只不过是 Microsoft 文化信息中的一个错误。
    【解决方案2】:

    小数位数由NumberFormatInfo.CurrencyDecimalDigits(https://msdn.microsoft.com/en-us/library/system.globalization.numberformatinfo.currencydecimaldigits(v=vs.110).aspx)控制

    ms-MY 文化中,这个CurrencyDecimalDigits 默认为零,这会导致数字被四舍五入。 在其他文化中,例如 sv-SECurrencyDecimalDigits2,它们显示 1,64

    您可以通过指定{0:C2} 来控制它,也可以更改NumberFormatInfo 上的值,例如:

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

    如果您认为 CurrencyDecimalDigitsms-MY 不应该为零,我们可以将此反馈传递给 Windows 团队,因为他们控制着 Windows 上的文化数据。

    谢谢

    【讨论】:

    • 值得一提的是,Windows 10 已将 ms-MY 的区域性信息更新为具有 CurrencyDecimalDigits 为 2。因此原始发布的代码应该会产生所需的结果而无需任何更改(即 RM1.64)跨度>
    • 在 Windows Server 2012 R2 上,该数字仍为 0(截至今天)。 Windows Server 已安装 .NET 4.6 并具有最新更新。我认为这是一个错误,因为相同的代码在不同的操作系统上表现不同。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-15
    • 2010-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-07
    相关资源
    最近更新 更多