double x = 1;
double y = 3 * (1.0/3);
x == y
在我正在研究的一個簡報中,它說這個陳述在邏輯上是有問題的。我找不到爲什麼它是這樣的,我的意思是你使用==爲原語正確,或者它是邏輯上可疑的,因爲雙打沒有準確存儲或我缺少明顯的東西?謝謝邏輯上有問題?
double x = 1;
double y = 3 * (1.0/3);
x == y
在我正在研究的一個簡報中,它說這個陳述在邏輯上是有問題的。我找不到爲什麼它是這樣的,我的意思是你使用==爲原語正確,或者它是邏輯上可疑的,因爲雙打沒有準確存儲或我缺少明顯的東西?謝謝邏輯上有問題?
因爲1.0/3
是0.3333...
,最大容量爲double
。 3 * 0.3333...
是0.9999...
,最大容量爲一倍。
所以我們有問題1 == 0.9999...
,我想你可以稱之爲「邏輯上有問題」。
小心 - ['1'實際上等於0.999 ...'](http://en.wikipedia.org/wiki /0.999 ...) –
'1'等於'0.999 ...',其中有9個的無限數。但這不是9的無限數目,所以在這種情況下它們不會相等。但正如其他人在這裏提到的,這完全取決於雙打四捨五入。 –
這是因爲舍入誤差。這個問題類似於在處理不能以您使用的格式精確表達的數字時,小數的精度問題。
例如,對於小數精度的六位數字,對於1/3可以做的最好的是.333333
。但:
1/3 + 1/3 + 1/3
- > 0.33333 + 0.333333 + 0.33333 = 0.999999 != 1.000000
哎喲。對於2/3,您可以使用.666666
或.666667
,但無論哪種方式,都有問題。
如果2/3 - >.666666
然後:
2/3 + 1/3
- > 0.333333 + 0.666666 != 1.000000
哎喲。
如果2/3。 - >.666667
然後:
1/3 * 2 - 2/3
- > 0.333333 * 2.00000 - 0.666667 = 0.666666 - 0.666667 != 0
哎喲。
它與雙打類似。 This paper被認爲是該主題的權威性工作。簡單地說 - 除非你確切地知道你在做什麼,否則絕對不要比較浮點數是否相等。
正確。浮動和雙打被存儲爲2的冪而不是小數。在1/3的情況下,這會讓事情變得更糟。 – Vlad
這在邏輯上是有問題的,因爲最後的比較語句會評估爲false。雙打被存儲爲一系列兩個冪。所以像1/2和1/4和1/8這樣的值實際上可以用浮點格式來表示,但不是1/3。將接近1/4 + 1/64 + ...現在有這樣它可以準確地將apprroximate 1/3
比較彩車正確的方法是這樣的:
Math.double.abs (x - y) > tol
哪裏tol設置爲足夠小的值,具體取決於您的應用。例如,大多數圖形應用程序在tol = 0時運行良好。00001
因爲雙打不完全
更多或更少的存儲
邏輯上有問題。
作爲一般規則,double
不能代表實數的精確值。值1/3
就是一個例子。
某些數字可以可以精確地表示爲double
值。例如1.0
和3.0
。但是,除法運算符產生一個無法表示的數字(在這種情況下)。
一般情況下,使用==
比較double
或float
值的任何代碼是有問題的......在您需要仔細分析每一種情況下知道使用==
是否正確感。 (和分析不直觀誰被教導在很小的時候就做算術基地10人!)
從軟件工程的角度來看,事實上,你需要向做不同個案==
用法的案例分析使其成爲可疑的做法。良好的軟件工程(部分)是關於消除錯誤和錯誤來源。
不要雙倍涉及小數,1和3不會? – nmagerko
這是後者。雙打精度有限,舍入誤差累積。 – goto10
*哪個*語句在邏輯上有問題?比較表達式在邏輯上是有問題的,因爲您沒有在任何地方使用結果。 – EJP