2014-02-13 25 views
1

這種情況讓我很困惑:我有一個.NET應用程序正在執行浮點數計算。這似乎有問題做分裂,Math.Pow和Math.Exp。例如:在.NET中錯誤的浮點數計算

double _E1 = 20616579.5; 
double sub = 19000; 
double total = 19623; 
double percent = sub/total;     //0.96825152635574341 
double _result1 = Math.Pow(_E1, percent);  //12078177.0 
double _result2 = Math.Exp(percent * Math.Log(_E1)); //12078184.730266357 

所有三種結果,百分比,_result1和_result2是不正確的(你可以用計算器來驗證)。

我有運行相同的代碼中的另一個.NET程序,在同一臺機器上,給出了正確的結果:

  • _result1 = 12078180.370260473
  • _result2 = 12078180.370260468
  • 百分率爲0.96825154155837534

僅通過查看百分比的結果,精度僅爲7位十進制數字。 Double通常爲16位十進制數字。

我還有一個更簡單的例子如下: enter image description hereenter image description here

_outcome等於有些可笑號。但是當把光標放在「*」的上方時,它會顯示正確的結果。

請幫忙,在過去的幾天裏讓我瘋狂。

更新:問題解決了。 DirectX是罪魁禍首。請參閱:Can floating-point precision be thread-dependent?

+0

的[?爲什麼不能十進制數字精確二進制表示]可能重複(HTTP ://www.stackoverflow.com/questions/1089018/why-cant-decimal-numbers-be-represented-exactly-in-binary) –

+0

什麼版本的.NET?我得到了完全相同的結果(對'_result1'和'_result2'的'12078180.3702605'在LinqPad中,其目標是.NET 4.x. –

+1

@MattBurland我不認爲這是同一個問題 - 'double'有很多精度和這兩個表達式應該會導致相同的答案 –

回答

0

Double僅具有15-16位的精度。我認爲這是你得到你的錯誤的地方。

嘗試使用十進制(http://msdn.microsoft.com/en-us/library/364x0z75.aspx)代替。可以處理28-29位數字。

+2

'Math.Pow'和'Math.Exp'只接受'double'參數,所以你不得不轉換爲'double'。此外,不一致性顯示在第7位數字上,因此「雙」應該具有足夠的精度。 –

+1

雙倍不應該是問題。我有另一個.net程序在同一臺機器上並排運行。相同的代碼給出不同的結果! – user3306496

1

您的確切代碼不會編譯(您有percent聲明兩次)。我懷疑其他地方有你沒有發佈的轉換(可能轉換到float某處會將精度降低到6-7位)。

當我在LinqPad運行代碼(減去percent額外的聲明),我得到正確的結果:

void Main() 
{ 
    double _E1 = 20616579.5; 
    double sub = 19000; 
    double total = 19623; 
    double percent = sub/total;     
    double _result1 = Math.Pow(_E1, percent);  
    double _result2 = Math.Exp(percent * Math.Log(_E1)); 

    percent.Dump();  // 0.968251541558375 
    _result1.Dump(); // 12078180.3702605 
    _result2.Dump(); // 12078180.3702605 
} 
+1

爲什麼人們投票呢?也許是因爲他們認爲它更適合作爲評論,因爲它沒有回答這個問題?但它可能實際上有答案:錯誤顯然太大而不能成爲普通的浮點舍入問題,所以它可能是一個錯誤,很可能是這個答案所暗示的性質。 –

+0

感謝Mark Dickinson和D Stanley的觀察,以下內容足以重現錯誤行爲:將'percent'轉換爲'float'。將'_result1'轉換爲'float'。將'Math.log(_E1)'轉換爲'float'並使用'float'算法將其乘以'percent'(在計算'_result2'的表達式中)。 –