2011-07-30 64 views
4

可能重複:!
problems in floating point comparison浮點比較`一個= 0.7`

#include <stdio.h> 
#include <conio.h> 

main() 
{ 
    float a = 0.7; 
    if(a < 0.7) 
     printf("C"); 
    else 
     printf("C++"); 
} 

在上面的代碼中,輸出是C。我在Code :: Blocks和Pelles C中試過這段代碼,但得到了相同的答案。我想知道詳細的原因!

+6

看看[浮點指南](http://floating-point-gui.de/)和[每個計算機科學家應該知道的有關浮點運算的知識](http://download.oracle。 com/docs/cd/E19957-01/806-3568/ncg_goldberg.html) – Bart

回答

19

在二進制,0.7是:

b0.1011001100110011001100110011001100110011001100110011001100110... 

然而,0.7是一個雙精度文字,其值0.7舍入到最接近的表示的雙精度值,這是:

b0.10110011001100110011001100110011001100110011001100110 

十進制,就是這樣:

0.6999999999999999555910790149937383830547332763671875 

當你寫,即雙值再次舍入到單精度和a得到二進制值:

b0.101100110011001100110011 

這正是

0.699999988079071044921875 

十進制。

當您執行比較(a < 0.7)時,您將此單精度值(轉換爲double,因爲所有單精度值都可以雙精度表示,因此不轉爲double)與原始雙精度值進行比較。因爲

0.699999988079071044921875 < 0.6999999999999999555910790149937383830547332763671875 

比較正確返回true,並且您的程序打印"C"

請注意,這與C++沒有任何區別,相反的代碼出現。有一些(數字上不安全的)編譯器優化可以改變行爲,但這些不是C或C++特有的。

+0

好的demontstration,+1 – unkulunkulu

+0

好的...非常感謝你!它幫助了很多! –

8

這是因爲0.7的類型爲double,所以a轉換爲double並在此類型中進行比較。由於0.7在二進制浮點中不能完全表示,因此會出現舍入錯誤並且比較成立。

您可以:

if(a < 0.7f) { 
.... 

但實際上這種影響是真實的C++,這樣你的條件是不完全合法的。

+0

好的。 –

3

巴特給了在他的評論很好的參考,但我也建議這個非常簡單的規則:當您使用浮點數

並非所有的數字可以精確地用計算機來表示,所以一旦(例如作爲浮點數和雙精度數),您應該期望在每個存儲的數字中可能存在一個小的,不可預知的錯誤。不,它不是真正的隨機或不可預測的,但是直到你對它有更多的瞭解,你纔會認爲它是不可預測的。因此,比較例如a < 0.7可能是事實,它可能不是。不要編寫依賴它的代碼。

+0

我從來沒有使用這種比較,但如果我必須比較一些浮點值呢? –