我已经阅读了几篇关于某些数据类型用于存储货币金额的危险的文章。不幸的是,有些概念并不在我的舒适区。
阅读这些文章后,在C#中使用资金的最佳做法和建议是什么?我应该使用少量的特定数据类型和更大数量的不同数据类型吗?此外,我在英国,这意味着我们使用,(例如£4,000,而其他文化代表不同的数量)。
答案 0 :(得分:16)
十进制是货币金额最明智的类型。
十进制是一个浮点数10数字类型,精度为28+十进制数。使用Decimal,您将获得比使用base 2 Double类型更少的惊喜。
Double使用的内存是Decimal的一半,而Double会因为许多常见浮点运算的CPU硬件而快得多,但它不能准确地代表大多数基本10分数(例如1.05)并且准确度较低15+精度的十进制数字。 Double确实具有更多范围的优势(它可以代表更大和更小的数字),这对于某些计算可以派上用场,特别是一些统计计算。
您的问题的一个答案是,Decimal是固定点,带有4位十进制数字。不是这种情况。如果您对此有疑问,请注意以下代码行产生0.0000000001:
Console.WriteLine("number={0}", 1m / 10000000000m);
说了这么多,有趣的是,世界上使用最广泛的用于处理货币金额的软件Microsoft Excel使用了双打。当然,他们必须通过大量的箍来使其运作良好,并且仍然有一些不足之处。在Excel中尝试这两个公式:
第一个产生0,第二个产生〜-2.77e-17。在某些情况下,Excel在添加和减去数字时实际上会对数字进行按摩,但并不是在所有情况下。
答案 1 :(得分:8)
由于舍入错误,您不应使用浮点数。小数类型应该适合你。
答案 2 :(得分:6)
Martin Fowler建议使用Money class。请参阅相关链接。他的想法有很多实现,或者你可以编写自己的想法。 Fowler自己的实现是用Java编写的,所以他使用了一个类。我见过的C#版本使用了一个结构,这看起来很合理。
答案 3 :(得分:2)
我使用值对象来保存金额(作为decimal
)和货币。这允许同时使用不同的货币。 decimal
是.NET推荐的数据类型。
答案 4 :(得分:0)
我的建议是使用Decimal,如果需要除法,则按其他人推荐使用。对于简单的计数应用程序,我建议使用Integer类型。对于这两种类型,我总是会研究最低的货币面额。 (即加拿大/美国的美分)
我喜欢@dangph添加的Fowler's Money调用理论。
答案 5 :(得分:0)
无论您做什么,请确保您了解如何在应用程序的每个层级中处理货币金额。
我曾经花了一周时间跟踪1¢错误,因为SQLServer和.Net使用不同的舍入货币的方式,并且应用程序在处理某些类型的计算方面不一致 - 有时它们是在SQL中完成的,有时是在。净。如果您有兴趣,请查看“bankers' rounding”。
还有与格式化货币相关的问题 - 不确定您是否必须处理非英国金额,其他语言/文化等,但这会增加另一层次的复杂性。
答案 6 :(得分:0)
正如您在问题中指出的那样,除了使用适当的数据类型外,您的程序处理货币转换的程度非常重要。这个问题当然不是专属于货币。 Jeff Atwood发表了一篇很好的文章,总结了The Turkey Test的优点。