2009-07-28 40 views
2

我使用下面的代碼段,並在一些神祕的情況下,加入的結果並不像它應該是:添加兩個雙誤給出結果

double _west = 9.482935905456543; 
double _off = 0.00000093248155508263153; 
double _lon = _west + _off; 

// check for the expected result 
Debug.Assert(_lon == 9.4829368379380981); 
// sometimes i get 9.48293685913086 for _lon (which is wrong) 

我使用一些本地的DLL在我的應用程序中,我懷疑有些DLL負責這個「錯誤計算」,但我需要弄清楚哪一個。 任何人都可以給我一個提示如何找出我的問題的根源?

+0

我想說這裏適用於兼作得好:http://stackoverflow.com/questions/ 1193554 /遇到問題時使用float-in-objective-c/1193607#1193607 – 2009-07-28 12:11:54

+0

問題的根源是由浮點精度的錯誤設置引起的。有人將浮點精度設置爲24位,這會導致計算錯誤。使用_fpreset或_controlfp(MSVC運行時DLL)可以解決這個問題,但是它仍然是設置這個精度的神祕之處嗎? – 2009-07-29 15:10:23

回答

9

雙不完全準確,請嘗試使用十進制而不是

採用雙層的advanteage和漂浮在小數是性能

+1

-1一個`Decimal`怎麼能比`Double`提供更好的性能?你的CPU知道如何處理`Singles`和`Doubles`,但是`Decimal`上的所有操作都必須在內存中發生,因爲內存速度較慢。 – 2009-07-28 12:25:42

2

起初我以爲這是一個舍入誤差,但實際上它是你的說法是錯誤。試着增加你的計算整個結果無需您任意四捨五入。

試試這個:

using System; 

class Program 
{ 
    static void Main() 
    { 
     double _west = 9.482935905456543; 
     double _off = 0.00000093248155508263153; 
     double _lon = _west + _off; 

     // check for the expected result 
     Console.WriteLine(_lon == 9.48293683793809808263153);  
    } 
} 

未來雖然它是最好的,你需要避免通常與System.SingleSystem.Double類型相關聯的舍入誤差的情況下使用System.Decimal

話雖這麼說,但是,這是不是這裏的情況。通過在給定點任意四捨五入數字,你假定這個類型也會在同一個點上圓整,這不是它的工作原理。浮點數被存儲到它們的最大表示容量,並且只有達到該閾值時才進行舍入。

0

您正在被舍入和精度問題咬傷。請參閱this。十進制可能會有幫助。有關轉換和舍入的詳細信息,請轉至here

從MSDN:

當轉換浮點或雙精度到十進制,源值轉換爲十進制表示,並且如果需要的28位小數後四捨五入到最接近的數字。取決於源值的值,可能會發生以下結果之一:

如果源值太小而不能表示爲小數,結果變爲零。

如果源值爲NaN(非數字),無窮大,或過大而不能表示爲小數,一個發生OverflowException異常。

0

問題是,雙精度只有15 - 16位(你似乎需要更多的精度在你的例子中),而十進制精度爲28 - 29.你怎麼轉換之間的雙精度和十進制?

0

不能代表在精確的二進制系統浮點十進制系統中的每個浮點數,這甚至是沒有直接關係的「小」的十進制數是怎麼了,有些數字只是不「配合「很好地在基地-2。

使用較長的位寬在大多數情況下有所幫助,但並非總是如此。

Decimal(128位浮點)精度指定常量,使用此聲明:

decimal _west = 9.482935905456543m; 
decimal _off = 0.00000093248155508263153m; 
decimal _lon = _west + _off;