2015-05-15 88 views
-1

問題不是爲什麼0.1 + 0.9不等於1.0。它關於平等的不同行爲。浮點數的意外結果等於

有人可以解釋爲什麼下面的例子工作不同。

float q = 0.1f; 
float w = 0.9f; 
float summ = q + w; 

q + w == 1.0f; // False 
summ == 1.0f; // True 

爲什麼運算符==的工作方式不同?

+1

'summ == 1.0f'也不應該是'false'嗎? –

+0

[language-agnostic-is floating point math broken?](http://stackoverflow.com/q/588004/995714) –

+1

LưuVĩnhPhúc,這個問題不是爲什麼'0.1 + 0.9!= 1'。這是關於爲什麼我對等運算符有不同的結果。 – user854301

回答

2

問題出在這樣的事實,即中間計算的執行精度要高一些,而且精度要回到float的規則在每種情況下都不相同。

根據the docs

默認情況下,在x86架構上的代碼編譯器將使用協處理器的80位寄存器來保存浮點計算的中間結果。

...編譯器執行上float類型的變量取整到正確的精度分配和管型和當參數被傳遞給功能」

float summ = q + w是一個賦值,並因此被舍入爲最近float,其在此情況下爲1。

q + w == 1.0f既不是鑄造,分配或函數調用,所以相加的結果仍然是擴展精度浮點數,這是接近的,但不相等,爲1

+0

在這種情況下,如果我們強制演員陣容,它會工作嗎?就像:((float)(q + w)== 1.0f' – Kryptos

+0

@Simon Byrne,這就是我一直在尋找的東西。謝謝! – user854301

+0

@Kryptos是的,它應該。 –

2

進一步展望IL:

summ被存儲在本地型float32

IL_000d: ldloc.0 
IL_000e: ldloc.1 
IL_000f: add 
IL_0010: stloc.2 

的在q + w == 1.0f使用q + w結果不爲;它是在一個比較

IL_0011: ldloc.0 
IL_0012: ldloc.1 
IL_0013: add 
IL_0014: ldc.r4  1. 
IL_0019: ceq 

直接使用推測的summ在本地存儲裝置它失去足夠的精度,它變成等於1.0f

+0

我同意你的意見,但仍然... – user854301

+1

由於我不能發表一個答案(由於重複塊),原因是在'q + w =​​= 1.0f'中,加法的結果不是被四捨五入成爲「浮動」。根據文檔「...編譯器對浮點類型的變量執行四捨五入到指定和轉換的正確精度,以及何時將參數傳遞給函數」 - https://msdn.microsoft.com/en-us/library /e7s85ffb.aspx –

+1

@SimonByrne好點,通過規範總比結果更好。隨意張貼,作爲答案,我不同意關閉愚蠢。 – Rawling