簡體   English   中英

小數vs再次翻倍

[英]decimal vs double again

我支持財務.net應用程序。 有很多建議將十進制數據類型用於財務工作。

現在我被困在這里:

decimal price = 1.0m/12.0m;
decimal quantity = 2637.18m;
decimal result = price * quantity;  //results in 219.76499999999999999999999991

問題在於,向我們的客戶收取的正確值是219.77(舍入函數MidpointRounding.AwayFromZero)而不是219.76。

如果我將所有內容都更改為兩倍,它似乎可以工作:

double price = 1.0/12.0;
double quantity = 2637.18;
double result = price * quantity;  //results in 219.765

我可以將所有內容更改為兩倍嗎? 分數還會有其他問題嗎?

我認為這個問題不同於.NET中的十進制,浮點數和雙精度之間的區別 因為它並沒有真正向我解釋為什么十進制數據類型更精確的結果(在上面的示例中)比精度數據類型使用更少字節的結果更不准確。

推薦使用十進制的原因是,所有可以表示為非重復小數的數字都可以准確地以十進制類型表示。 現實世界中的貨幣單位始終是非重復的小數。 正如其他人所說,您的問題是,由於某種原因,您的價格無法表示為非重復的小數。 那就是0.083333333... 使用雙精度實際上並沒有幫助精度-雙精度也不能精確表示1/12。 在這種情況下,缺乏准確性不會造成問題,但在其他情況下可能會造成問題。

同樣更重要的是,選擇使用雙精度將意味着您還有很多數字可能無法完全准確地表示出來。 例如0.01、0.02、0.03 ...是的,您可能會關心的很多數字都不能准確地表示為雙精度數。

在這種情況下,價格從何而來的問題確實很重要。 無論您在哪里存儲該價格,幾乎肯定都不會完全存儲1/12 您要么已經存儲了一個近似值,要么價格實際上是計算的結果(或者您正在使用一個非常不尋常的數字存儲系統來存儲有理數,但這似乎不太可能)。

您真正想要的是可以表示為兩倍的價格。 如果那是您需要的,但是您可以對其進行修改(例如,除以12以從年度中獲得每月費用),則需要盡可能晚地進行該划分。 而且很可能您還需要將月成本計算為未償余額的除法。 我的意思是,如果您每年支付10美元的月度分期付款,您可能會在第一個月收取0.83美元。 然后第二個月您要收費($ 10-0.83)/ 11。 這將再次為0.83。 在第五個月,您收取(10-0.83 * 4)/ 8,現在為0.84(四舍五入)。 然后下個月其(10-0.83 * 4-0.84)/ 7,依此類推。 這樣,您可以保證總費用是正確的,並且不必擔心復合錯誤。

歸根結底,您是唯一一個可以判斷是否可以重新架構系統以消除所有舍入錯誤,或者是否必須按照我建議的方式緩解它們的人。 最好的選擇是閱讀有關浮點數的所有信息,包括十進制和二進制,以便您完全理解選擇一個而不是另一個的含義。

通常,在財務計算中,乘法和除法應以某種方式四舍五入到小數位數。 (大多數貨幣系統僅使用10個基數的貨幣;在這些系統中,非10個基數的貨幣會發生,如果出現這種情況,則很少見。)將價格除以12而沒有更多的貨幣,總不能得出基數。 10號; 業務邏輯將規定如何對價格進行四舍五入,包括結果將具有的小數位數。 根據業務邏輯的不同,諸如0.083333333333333333類的結果可能不合適。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM