2011-04-06 79 views
5

我一直在嘗試天花板函數,並得到了一些奇怪的結果。如果我執行一個小數乘以百的小數運算,我會得到一定的結果。但是,如果我直接執行該乘法的結果ceil,我會得到一個完全不同的輸出。另一個轉折是,這些不同的結果只出現在某些數字上。任何幫助,將不勝感激。C++天花板函數的奇怪結果

#include <stdio.h> 
#include <cmath> 

int main() 
{ 
cout << "The ceiling of " << 411 << " is " << ceil(411) << endl; 
cout << "The ceiling of 4.11*100 is " << ceil(4.11*100) << endl; 

cout << "The ceiling of " << 121 << " is " << ceil(121) << endl; 
cout << "The ceiling of 1.21*100 is " << ceil(1.21*100) << endl;; 
} 


OUTPUT: 

The ceiling of 411 is 411 
The ceiling of 4.11*100 is 412 
The ceiling of 121 is 121 
The ceiling of 1.21*100 is 121 

回答

9

這裏的問題是浮點數不能由計算機可靠地表示。這意味着,4.11不表示爲4.11,但非常接近它。當這個「非常接近4.11」的數字乘以100,該產品的ceil原來是412,很讓你意外!但是一旦你知道如何存儲和檢索浮點數字,這並不意外。


剛看到這個有趣的演示:

float a = 3.2; //3.2 is double! 
if (a == 3.2) 
    cout << "a is equal to 3.2"<<endl; 
else 
    cout << "a is not equal to 3.2"<<endl; 

float b = 3.2f; //3.2f is a float. Note: f is appended to make it float! 
if (b == 3.2f) 
    cout << "b is equal to 3.2f"<<endl; 
else 
    cout << "b is not equal to 3.2f"<<endl; 

輸出:

一個不等於3.2
b等於3.2F

做實驗這裏在ideone:http://www.ideone.com/pAGzM

嘗試將變量a的類型從float更改爲double,請參閱the result again

+0

但即使我使用double也會發生同樣的情況。這一直髮生在一些數字上,但不會發生在別人身上,這真的讓我感到困惑。 – sowmya 2011-04-06 07:07:23

+0

@sowmya:偶數是浮點數。 'float'類型的精度低於'double'類型。這意味着,'雙'更精確地存儲*比較*,但這並不意味着它代表它「準確地」。事實上,'double'就是這樣命名的,因爲它是雙精度浮點數。看到這個:http://en.wikipedia.org/wiki/Double_precision_floating-point_format – Nawaz 2011-04-06 07:09:28

+1

你在示例代碼中使用'double'。那裏沒有使用'浮動'號碼。 – 2011-04-06 07:13:04

5

FAQ

[29.16]爲什麼浮點所以 不準確?爲什麼不打印 0.43?

#include <iostream> 

int main() 
{ 
    float a = 1000.43; 
    float b = 1000.0; 
    std::cout << a - b << '\n'; 
    ... 
} 

免責聲明:挫折與 四捨五入/截斷/近似 是不是一個真正的C++的問題;這是一個 計算機科學問題。然而, 人不斷詢問 comp.lang.C++,所以接下來是 名義答案。

答案:浮點數是 的近似值。 32位浮點數的IEEE標準支持1位符號,8位 位指數,以及23位尾數 。由於標準化的 二進制點尾數總是有 形式1.xxxxx ...領先的1是 下降,你有效地得到24 比特的尾數。數字1000.43 (以及很多很多其他的,包括一些真正常見的如0.1)不是 ,它們可以用浮點數或 雙精度格式精確表示。 1000。43實際上是 ,表示爲以下 位模式(「s」顯示符號位的位置 ,「e」顯示指數位的位置 ,並且 「m」顯示位圖的位置 尾數比特):

seeeeeeeemmmmmmmmmmmmmmmmmmmmmmm 
01000100011110100001101110000101 

移位的尾數是 1111101000.01101110000101或1000 +一萬六千三百八十四分之七千〇四十五。小數部分是 0.429992675781。用24位尾數你只能獲得約1分的浮點精度16M。雙 類型提供更高的精度(尾數的53位 )。

而且,看到[29.17] Why doesn't my floating-point comparison work?

1

ceil(x)函數返回的最小整數不那麼x少。

由於您輸入的常量(如4.111.21)沒有精確表示 - 它們可能恰好表示爲稍小的數字或稍大的數字,或者極少數情況下數字相同。例如。您的編譯器將常量4.11表示爲稍大的數字,因此4.11*100恰好略大於411因此ceil(4.11*100) == 412(因爲412是最小數字不小於數字略大於411),但1.21表示爲稍小的數字,因此1.21*100是略小於121,所以ceil(1.21*100)==121

另請注意,乘法也不準確。