2013-10-18 191 views
0

我使用小數類型進行高精度計算(貨幣)。小數的精度

但我今天碰到這個簡單的除法就來了:

1/(1/37)這將導致37再次

http://www.wolframalpha.com/input/?i=1%2F+%281%2F37%29

但是C#給我: 37.000000000000000000000000037M

我想這兩個: 1m/(1m/37m);Decimal.Divide(1, Decimal.Divide(1, 37))

但都產生相同的結果。行爲如何解釋?

+0

更多信息:http://stackoverflow.com/questions/618535/what-is-the-difference-between-decimal-float-and-double-in-c?rq=1 –

+0

我想你應該看看http://msdn.microsoft.com/en-us/library/364x0z75.aspx - 十進制不會採取(1/37)並將其表示爲分子/分母成員。它只是一個數量更大,範圍更小的數字,這使得它更適合於某些計算。越小的範圍和更大的尺寸意味着小數具有更高的精度。 – Warty

+0

[每個程序員應該知道什麼關於浮點運算](http://floating-point-gui.de/) –

回答

4

Decimal將該值存儲爲十進制浮點值,並且精度有限。由於1/37的結果存儲爲0.027027027027027027027027027M,因此不會預先存儲。真正的數字組027無限期地以十進制表示。因此,對於每個可能的數字,您都無法獲得十進制表示的精確數字。

如果在同一計算中使用Double,則在這種情況下最終結果是正確的(但這並不意味着它總是會更好)。

有關該主題的一個很好的答案就在這裏:Difference between decimal, float and double in .NET?

1

十進制數據類型有28-29顯著數字的準確性。 所以你必須明白的是,當你考慮28-29個重要數字時,你仍然不確切。

所以,當你計算(1/37)的十進制值時,你必須注意的是,在這個階段你只能得到28-29位數的精確度。例如,當您獲取2位有效數字時,1/37爲0.02,當您獲取3位有效數字時爲0.027。想象一下,在每種情況下,用這些值除1。在第一種情況下得到50,在第二種情況下得到37.02 ...考慮28-29數字(十進制)會使您的準確度達到37.000000000000000000000000037。如果你必須得到一個確切的37,你只需要比十進制提供的有效數字多28-29。

始終使用最大有效位數進行計算,並只用Math.Round對您的答案進行四捨五入以獲得所需結果。

+0

你說增加數字,但結果是無限的,所以甚至會有幫助? – YesMan85

+0

如果在28-29位數字中無法得到確切的答案,那麼使用小數時,進一步的計算就會像您所說的那樣產生微小的差異。因此,無限的結果是最接近你可以得到的。 – simba

+0

我看到是的,我現在添加了一個'Decimal.Round(x,5)',可以得到好的結果。 – YesMan85