2011-04-26 62 views
0

我收到交易分配的FIX消息,其中價格在美分(ZAR/100)中給出,但佣金在蘭特中給出。這些值由常數表示。當我運行這個計算時,commPerc1顯示值爲0.099999999999999978,而commPerc2顯示爲0.1。這些值看起來相差x10,但隨着計算回到蘭德commRands1commRands2分別顯示非常相似的值336.4831554和336.48315540000004。這個C#財務計算中的浮點問題在哪裏?

private const double Price = 5708.91; 
private const double Qty = 5894; 
private const double AbsComm = 336.4831554; 

static void Main() 
{ 

    double commCents = AbsComm * 100; 
    double commPerc1 = commCents/(Qty * Price) * 100; 
    double commRands1 = (Qty * Price) * (commPerc1/100)/100; 

    double commPerc2 = (AbsComm/(Qty * (Price/100))) * 100; 
    double commRands2 = (Qty * Price) * (commPerc2/100)/100; 
} 

請注意: 我處理的遺留代碼在這裏,其中一個轉換爲十進制會涉及一些變化和QA,所以現在我必須接受double

+6

憑啥你用'double',而不是'Decimal'的財務計算? – CodesInChaos 2011-04-26 08:49:11

+0

你在哪裏看到10倍的差異? '0.099 ... = 0.1',你看到的是一些浮點錯誤的影響,沒有什麼特別的。 'commPerc1'等於'commPerc2',忽略那些微不足道的錯誤。 – Darhuuk 2011-04-26 08:56:09

回答

5

不要使用double進行財務計算,請使用decimal來代替。無論如何,物理測量值的浮點數都可以。但是對於財務計算,您正在使用確切的值,因爲浮點表示,您不能承受錯誤。這就是decimal是爲製作:

十進制值類型適用於需要大量的顯著整數和小數位數的財務計算,沒有舍入誤差。

(from MSDN)

5

浮點問題是無處不,因爲所有你的價值觀是double類型,這是一個雙精度浮點型,而不是一個基10個數字式的。 (因此,所有正在執行的計算都是浮點計算。)

您應該聲明變量decimal。這種類型專門用於財務計算。

2

這是由於浮點數被存儲在內存中的方式。在處理財務計算時,您可以使用decimal而不是doublefloat

1

財務計算應該使用Decimal數據類型進行。由於指定的數字不能完全存儲在指定的位分配內,因此會將指定數字的「近似值」加倍存儲。

1

0.0999999999999999780.1不相差10倍,它們幾乎相同。就像0.999幾乎是1.

但是你真的應該使用Decimal而不是Double進行財務計算。 Double不能準確地表示數字,如0.1Decimal可以。 (另一方面,也不能完全表示1/3)。

此外Decimal有一個較大的尾數,並在發生溢出時拋出異常。

4

當運行該計算,commPerc1示出的0.099999999999999978的值,並且示出了commPerc20.1。這些值看起來有所不同x10

不,他們不是。只有一個無限小(但存在)的舍入差異。正如其他人已經指出的那樣,您絕對不應該將浮點數用於需要絕對精度的計算。有了浮點數,你總會有這樣的舍入誤差,例如金融客戶不喜歡書中缺失或額外的便士/美分。

+0

是的,謝謝。在我的腦海中,我錯誤地將0.09中的9個變成了1,給出了0.01。 – ProfK 2011-04-26 09:22:14