問題不是爲什麼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
爲什麼運算符==
的工作方式不同?
問題不是爲什麼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
爲什麼運算符==
的工作方式不同?
問題出在這樣的事實,即中間計算的執行精度要高一些,而且精度要回到float
的規則在每種情況下都不相同。
根據the docs
默認情況下,在x86架構上的代碼編譯器將使用協處理器的80位寄存器來保存浮點計算的中間結果。
...編譯器執行上
float
類型的變量取整到正確的精度分配和管型和當參數被傳遞給功能」
float summ = q + w
是一個賦值,並因此被舍入爲最近float
,其在此情況下爲1。
q + w == 1.0f
既不是鑄造,分配或函數調用,所以相加的結果仍然是擴展精度浮點數,這是接近的,但不相等,爲1
在這種情況下,如果我們強制演員陣容,它會工作嗎?就像:((float)(q + w)== 1.0f' – Kryptos
@Simon Byrne,這就是我一直在尋找的東西。謝謝! – user854301
@Kryptos是的,它應該。 –
進一步展望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
。
我同意你的意見,但仍然... – user854301
由於我不能發表一個答案(由於重複塊),原因是在'q + w == 1.0f'中,加法的結果不是被四捨五入成爲「浮動」。根據文檔「...編譯器對浮點類型的變量執行四捨五入到指定和轉換的正確精度,以及何時將參數傳遞給函數」 - https://msdn.microsoft.com/en-us/library /e7s85ffb.aspx –
@SimonByrne好點,通過規範總比結果更好。隨意張貼,作爲答案,我不同意關閉愚蠢。 – Rawling
'summ == 1.0f'也不應該是'false'嗎? –
[language-agnostic-is floating point math broken?](http://stackoverflow.com/q/588004/995714) –
LưuVĩnhPhúc,這個問題不是爲什麼'0.1 + 0.9!= 1'。這是關於爲什麼我對等運算符有不同的結果。 – user854301