2011-11-02 130 views
1
double x = 1; 
double y = 3 * (1.0/3); 


x == y 

在我正在研究的一個簡報中,它說這個陳述在邏輯上是有問題的。我找不到爲什麼它是這樣的,我的意思是你使用==爲原語正確,或者它是邏輯上可疑的,因爲雙打沒有準確存儲或我缺少明顯的東西?謝謝邏輯上有問題?

+0

不要雙倍涉及小數,1和3不會? – nmagerko

+2

這是後者。雙打精度有限,舍入誤差累積。 – goto10

+1

*哪個*語句在邏輯上有問題?比較表達式在邏輯上是有問題的,因爲您沒有在任何地方使用結果。 – EJP

回答

5

我認爲你已經明白了:由於數據類型是雙精度型,而不是int或Integer,因此得到的x和y可能不完全相等。

+1

我正要回答,當我看到這個,所以認爲我會加入它。其使用「雙」使其變得棘手!不能保證這會永遠評估爲真。 y可以是0.9999,或1.00001 – aishwarya

+0

很酷。無論如何,我認爲Jonathan Newmuis的回答比我的要好。 – bbg

+0

如果您使用'int' 3 *(1/3)!= 1;) –

2

因爲1.0/30.3333...,最大容量爲double3 * 0.3333...0.9999...,最大容量爲一倍。

所以我們有問題1 == 0.9999...,我想你可以稱之爲「邏輯上有問題」。

+0

小心 - ['1'實際上等於0.999 ...'](http://en.wikipedia.org/wiki /0.999 ...) –

+0

'1'等於'0.999 ...',其中有9個的無限數。但這不是9的無限數目,所以在這種情況下它們不會相等。但正如其他人在這裏提到的,這完全取決於雙打四捨五入。 –

1

這是因爲舍入誤差。這個問題類似於在處理不能以您使用的格式精確表達的數字時,小數的精度問題。

例如,對於小數精度的六位數字,對於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被認爲是該主題的權威性工作。簡單地說 - 除非你確切地知道你在做什麼,否則絕對不要比較浮點數是否相等。

+0

正確。浮動和雙打被存儲爲2的冪而不是小數。在1/3的情況下,這會讓事情變得更糟。 – Vlad

3

這在邏輯上是有問題的,因爲最後的比較語句會評估爲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

0
因爲雙打不完全

更多或更少的存儲

邏輯上有問題。

  • 作爲一般規則,double不能代表實數的精確值。值1/3就是一個例子。

  • 某些數字可以可以精確地表示爲double值。例如1.03.0。但是,除法運算符產生一個無法表示的數字(在這種情況下)。

  • 一般情況下,使用==比較doublefloat值的任何代碼是有問題的......在您需要仔細分析每一種情況下知道使用==是否正確感。 (和分析不直觀誰被教導在很小的時候就做算術基地10人!)

  • 從軟件工程的角度來看,事實上,你需要做不同個案==用法的案例分析使其成爲可疑的做法。良好的軟件工程(部分)是關於消除錯誤和錯誤來源。