2013-04-10 58 views
0

任何人都可以解釋這一點嗎?C#十進制分區(非常奇怪的行爲)

Decimal leftSide = 13.0M; 
Decimal rightSide = 1.0M; 
Decimal tmpDec = 39.0M; 

tmpDec * (rightSide/leftSide) = 2.9999999999999999999999999991 

tmpDec * rightSide/leftSide = 3 

我在第一個(右側/左側)失去了有效數字嗎?

+3

[每個計算機科學家應該知道的關於浮點運算的內容](http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg .html) – Habib 2013-04-10 12:31:51

+0

謝謝你的白皮書鏈接。 – 2013-04-10 12:45:20

回答

1

這是四捨五入(鬆動精度)的問題。

第一種情況首先執行除法並裁剪最後一個數字(自float(或double或decimal或任何其他固定精度數據類型)以來不能存儲無限長值的小數點後的第28位),然後執行裁剪的價值增加了​​3900萬次的損失。這已經變得很重要(現在不是28位數字問題,堅果20-22)並且不能捨入到3.0。

第二種情況首先執行乘法,不放寬精度並存儲每8位數字,然後以較小的精度寬鬆(小數點後6位)執行除法。因此在第一種情況下已經舍入到3.0而不是2.999999999999999999999。

+3

請詳細說明 – pordi 2013-04-10 12:33:38

+1

請詳細說明,很多... – bizzehdee 2013-04-10 12:33:54

+0

謝謝你的解釋,你已經證實了我的懷疑。 – 2013-04-10 12:45:53

1

十進制類型僅精確到29位有效數字。

2.9999999999999999999999999991

^擁有超過29個顯著數字。

如果您需要更高的精度,您可以使用System.Numerics.BigInteger(將其修改爲定點小數)。

+0

使用.NET 3.5,謝謝你的答案。 – 2013-04-10 12:41:01

-1

將無限多個實數擠壓成有限數量的比特需要近似表示。雖然有無限多的整數,但在大多數程序中,整數計算的結果可以存儲在32位中。相反,給定任意固定的位數,大多數使用實數的計算都會產生無法使用多位來精確表示的數量。因此,浮點計算的結果必須經過四捨五入以適應其有限表示。這個舍入誤差是浮點運算的特徵