2012-04-24 196 views
11

我有是找到在一個圖上的路徑,並輸出該累積重量的程序。圖形中的所有邊都有一個浮點形式的單個權重爲0到100,最多有2個小數位。0 + 0 + 0 ... + 0!= 0

在Windows/Visual Studio 2010中,對於包含0權重的邊的特定路徑,它輸出正確的總權重爲0.但是,在Linux/GCC上,程序說路徑的權重爲2.35503e-38。我曾經有過由浮點數造成的瘋狂錯誤的豐富經驗,但是0 + 0何時會等於0以外的任何東西?

我認爲導致這的唯一的事情是程序沒有把一些權重爲整數,使用隱式強制將它們添加到總量。但是0 + 0.0f仍然等於0.0f! 作爲一個快速解決方案,我減少總數爲0時小於0.00001,這足以滿足我的需要,現在。但是什麼vodoo導致這個?

注:我100%確信,沒有在圖中的權重超過我所提到的範圍內,所有在這個特殊的路徑中的權重都爲0

編輯:爲了詳細,我已經嘗試從文件中讀取權重並手動將它們設置爲代碼,等於0.0f除了將它們添加到總數之外,沒有其他操作在其上執行。

+19

你能構建一個最小的測試用例嗎? – 2012-04-24 18:22:33

+0

@OliCharlesworth這是我一直在努力做到的,迄今沒有運氣。相關代碼的數量太多,但我會繼續嘗試在較小範圍內重現該錯誤。我希望在這背後會有明顯的推理。 – 2012-04-24 18:24:28

+0

我會建議你看看機器epsilon的定義。這似乎是什麼導致你的錯誤在這裏。 – andre 2012-04-24 18:28:15

回答

11

因爲它是一個IEEE浮點號碼,它不完全等於零。

http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm

+3

但問題是:爲什麼? (如爲什麼它不是零)?但是,這還不能回答,因爲我們需要從OP中看到一個測試用例。 – 2012-04-24 18:29:47

+0

我在本科數值分析課程中研究了很多浮點問題,但我從未發現0 + 0應該是0以外的任何情況。我從來沒有做過任何其他操作。 – 2012-04-24 18:31:54

+0

http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm爲什麼0不是0?我認爲「零」部分表示0是0,並且在IEEE 754規則中有精確表示。 – 2012-04-24 18:31:57

3

這可能是因爲您的包含「0.0F」值花車實際上不是0.0F(位表示00000000),但計算結果爲約0.0個非常非常小的數目。由於IEEE754規範定義的浮點表示,如果你有,例如,一個非常小尾數和0指數,雖然它並不等於絕對的0時,將全面爲0。但是,如果你添加這些數字加在一起足夠的方式次數,這個非常小的數額將累積成最終將變爲非零的值。

下面是一個例子情況下,它給出了0的錯覺是非零:

float f = 0.1f/1000000000; 
printf("%f, %08x\n", f, *(unsigned int *)&f); 
float f2 = f * 10000; 
printf("%f, %08x\n", f2, *(unsigned int *)&f2); 

如果你指定文字到你的變量和添加他們,但是,它有可能,要麼編譯器不在存儲器中將0轉換爲0x0。如果是,這仍然發生,那麼它也有可能是你的CPU硬件有關於轉0到非零這樣做,可能會通過他們的驗證工作尖叫ALU操作時的錯誤。

然而,這是好事,記住,IEEE浮點只是一個近似值,和任何特定的浮點值不是一個確切的表示。所以任何浮點運算都會有一定的錯誤。

+0

不,這不像我的情況。我永遠不會分裂。我只將0和0.0f分配給變量,然後添加它們。 – 2012-04-24 18:40:30

+0

我給出了一個可能導致錯覺的例子。當然,許多不同的情況可能會導致類似的情況。 – 2012-04-24 18:41:52

+0

對,我從來沒有想過,添加常量0可能會導致這種情況。 – 2012-04-24 18:42:32

5

以最多2個小數位的浮點形式出現。

有沒有這樣的事情,作爲一個浮動與至多2位小數。浮點幾乎總是表示爲二進制浮點數(小數二進制尾數和整數指數)。如此多的(大多數)小數點後兩位數字不能完全表示。

例如,0.20f可以看作是一個天真圓形部分,但

printf("%.40f\n", 0.20f); 

會打印:0.2000000029802322387695312500000000000000。

看,它沒有2位小數,它有26!

當然,對於大多數實際應用來說,其差異可以忽略不計。但是如果你做了一些計算,你最終可能會增加舍入誤差並使其可見,特別是大約爲0.

+0

我知道這是非零值,但我的問題是在處理只有0時出現的。但是,對於大量零點稍微偏離的情況,或許正如另一個答案中指出的那樣引起了問題。 – 2012-04-24 18:35:40

+0

你怎麼知道你正在處理0?他們是編譯常量嗎?從文件讀取? – rodrigo 2012-04-24 18:37:03

+0

我嘗試使用常量並從文件中讀取數據。 – 2012-04-24 18:37:45

相關問題