#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中試過這段代碼,但得到了相同的答案。我想知道詳細的原因!
#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中試過這段代碼,但得到了相同的答案。我想知道詳細的原因!
在二進制,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++特有的。
好的demontstration,+1 – unkulunkulu
好的...非常感謝你!它幫助了很多! –
這是因爲0.7
的類型爲double
,所以a
轉換爲double
並在此類型中進行比較。由於0.7
在二進制浮點中不能完全表示,因此會出現舍入錯誤並且比較成立。
您可以:
if(a < 0.7f) {
....
但實際上這種影響是真實的C++,這樣你的條件是不完全合法的。
好的。 –
巴特給了在他的評論很好的參考,但我也建議這個非常簡單的規則:當您使用浮點數
並非所有的數字可以精確地用計算機來表示,所以一旦(例如作爲浮點數和雙精度數),您應該期望在每個存儲的數字中可能存在一個小的,不可預知的錯誤。不,它不是真正的隨機或不可預測的,但是直到你對它有更多的瞭解,你纔會認爲它是不可預測的。因此,比較例如a < 0.7可能是事實,它可能不是。不要編寫依賴它的代碼。
我從來沒有使用這種比較,但如果我必須比較一些浮點值呢? –
看看[浮點指南](http://floating-point-gui.de/)和[每個計算機科學家應該知道的有關浮點運算的知識](http://download.oracle。 com/docs/cd/E19957-01/806-3568/ncg_goldberg.html) – Bart