簡體   English   中英

圓形浮動具有非精確表示

[英]Rounding floats with non-exact representation

對於某些財務計算,我們在浮點數的舍入方面存在問題。

基本上,我們希望將貨幣金額(如1000000000.555)舍入為2位小數。 但是,此數字的浮點表示為1000000000.5549999,因此我們將向下舍入到1000000000.55而不是正確的1000000000.56。

我們有什么方法可以安全地解決這個問題嗎? 到目前為止,我們唯一想到的是始終在舍入操作之前添加最小的可表示浮點數,但我們不知道在所有情況下這是否安全。

代碼是用C語言編寫的,需要在windows32 / 64 / linux / solaris上運行,所以我們很遺憾無法獲得像.net中的Decimal數據類型這樣的好東西。

任何輸入都會有所幫助。

謝謝,里卡德

最常用的表示貨幣的方法是使用整數。 例如,在歐元區,一種常見的方法是用微歐元(1E-6)來表示價值。 你顯然會使用64位數學。 你會在整個應用程序中始終如一地使用它。 只有在人類I / O上你才能完成,你可以通過除以10000得到一個整數的分數。

這個故事的寓意永遠不會用浮點數代表金錢!

貨幣是分散的,大多數財務和會計法規都承認這一點。 你不能以3.145217美元的身價支付賬單。 雖然在17世紀,將硬幣投入鐵匠並讓他將一塊銀幣切成碎片是可以接受的(八塊碎片有很好的披薩切片標記來幫助這個過程!)今天它是不可能的。

例如,瑞士最小的硬幣是5 rappe,因此會計和賬單必須表示為最接近的5美分,即您無法獲得3.14瑞士法郎的賬單,必須是3.15瑞士法郎,或者如果您的供應商不太可能,則為3.10瑞士法郎慷慨,因為你只能支付3.10或3.15現金。

你也有兩種選擇。 獲取boost BigDecimal庫,它可以精確指定舍入。 或者,正如另一張海報所建議的那樣,使用long long表示您的金額為千分之一歐元,並且只顯示四舍五入。

另一種可能性是使用半美分單位,即55歐元35美分,內部代表11070美分,然后不必擔心任何標准會計交易的四舍五入。

我無法擔心您沒有正確地捕獲您的業務要求。 在我的上一個項目中,有超過一百頁的業務規則處理利率計算,至少40頁涉及計算的每個階段的小數位數或要使用的舍入算法。

我建議使用十進制數字包,例如decNumber

如果您在Windows中並且願意編寫托管C / C ++。

在大多數情況下,您只需使用十進制 來自MSDN

Decimal值類型適用於需要大量有效積分和小數位且沒有舍入誤差的財務計算。

如果您不能或不願意使用托管C / C ++,請查看十進制數字包,例如decNumber

在這兩種情況下,您都應該進行大量的單元和集成測試,以覆蓋帶有舍入的邊角情況。 他們會給你最大的痛苦。 四舍五入非常善於隱藏其他錯誤。

但是正如其他人所說的那樣,你要小心翼翼。 例如,在英國所得稅軟件規格中,大約一半的文本是關於在哪里以及如何(在每個地方不同)與圓形數字,因為你必須得到相同的結果,然后使用手動稅表。

暫無
暫無

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

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