我已閱讀了幾篇關於用於存儲貨幣金額的某些數據類型的風險的文章。不幸的是,一些概念不在我的舒適區。在C中處理貨幣金額的最佳做法#
閱讀完這些文章後,在C#中使用金錢工作的最佳實踐和建議是什麼?我應該使用少量的某種數據類型,還是使用其他數量較大的數據?此外,我在英國,這意味着我們使用,(例如4000英鎊,而其他文化不同地表示相同的金額)。
我已閱讀了幾篇關於用於存儲貨幣金額的某些數據類型的風險的文章。不幸的是,一些概念不在我的舒適區。在C中處理貨幣金額的最佳做法#
閱讀完這些文章後,在C#中使用金錢工作的最佳實踐和建議是什麼?我應該使用少量的某種數據類型,還是使用其他數量較大的數據?此外,我在英國,這意味着我們使用,(例如4000英鎊,而其他文化不同地表示相同的金額)。
由於舍入錯誤,您不應該使用浮點數。小數類型應該適合你。
我使用一個值對象來保存金額(作爲decimal
)和貨幣。這允許同時使用不同的貨幣。在.NET中,金錢的推薦數據類型爲decimal
。
十進制是貨幣金額最明智的類型。
十進制是浮點基數10數值類型,精度爲28+十進制數字。使用十進制,你將會有比使用基本2雙精度類型更少的驚喜。
Double使用一半的內存作爲十進制和雙精度,因爲許多常見浮點運算的CPU硬件會快得多,但它不能準確表示大多數基數爲10的分數(例如1.05),並且精度較低+精度的十進制數字。雙確實有更多範圍的優點(它可以代表更大和更小的數字),這對於一些計算尤其是一些統計計算來說可以派上用場。
你的問題的一個答案指出,十進制是4位十進制數字的固定點。不是這種情況。如果你懷疑這一點,請注意下面的代碼行產生0.0000000001:
Console.WriteLine("number={0}", 1m/10000000000m);
說了這一切,這是有趣的是,在世界上最廣泛使用的軟件與貨幣量的工作,Microsoft Excel中,使用雙打。當然,他們必須跳過很多環節才能使其運行良好,並且還有一些不盡人意的地方。在Excel中嘗試這兩個公式:
第一產量0,第二個產率〜-2.77e-17 。在某些情況下,Excel實際上會在添加和減去數字時按摩數字,但在所有情況下都不會。
整潔的Excel例子! – 2009-03-01 04:06:30
Martin Fowler建議使用Money class。查看鏈接的理由。他的想法有很多實現,或者你可以自己寫。福勒自己的實現在Java中,所以他使用了一個類。我見過的C#版本使用了一個結構,這似乎是合理的。
我的建議是使用十進制,正如其他人建議的,如果需要劃分。對於簡單的理貨應用,我會推薦一個Integer類型。對於這兩種類型,我總是會在最低的貨幣面額上工作。 (即加拿大/美國的美分)
我喜歡@dangph添加的Fowler Money的理論。
無論您做什麼,請確保您瞭解如何在應用程序的每一層處理貨幣金額。
我曾經花了一週的時間追蹤1美分的錯誤,因爲SQLServer和.Net使用不同的方式舍入貨幣,並且應用程序在處理某些類型的計算方面並不一致 - 有時它們是在SQL中完成的,有時在.net中。如果您有興趣,請查看「bankers' rounding」。
還有與格式化貨幣有關的問題 - 不確定是否必須處理非英國的金額,其他語言/文化等,但這會增加另一個級別的複雜性。
正如你在你的問題中指出的那樣,除了使用適當的數據類型,你的程序如何處理貨幣轉換也很重要。當然這個問題如果不是貨幣獨佔的話。 Jeff Atwood做了一篇很棒的文章,總結了執行The Turkey Test的優點。
我很想知道爲什麼有人投這個票。 – 2011-08-08 22:11:18
我投票只是爲了抵消反對票。我不認爲應該允許在沒有評論的情況下下決定票。 – 2012-12-06 19:37:45