2016-10-10 72 views
3

的考慮:輸出FMOD功能C++

#include <iostream> 
#include <cmath> 
#include <limits> 
using namespace std; 

int main() { 
    // your code goes here 
    double h = .1; 
    double x = 1; 
    int nSteps = abs(x/h); 

    double rem = fmod(x, h); 
    cout<<"fmod output is "<<rem<<endl; 
    if(abs(rem)<std::numeric_limits<double>::epsilon()) 
     cout<<"fmod output is almost near 0"<<endl; 

    rem = remainder(x,h); 
    cout<<"remainder output is "<<rem<<endl; 
    if(abs(rem)<std::numeric_limits<double>::epsilon()) 
     cout<<"remainder output is almost near 0"<<endl; 

    return 0; 
} 

鑑於int(x/h) == 10,我本來期望的fmod()結果接近0,但我得到的是0.0999999999。這是一個重大的差異。餘數()的結果仍然可以接受。代碼可以嘗試在http://ideone.com/9wBlva

爲什麼fmod()結果有顯着差異?

+0

C++和C Arent使用相同的語言 – amanuel2

+0

如果這樣不能自己回答您的問題,請閱讀文檔。 'fmod'和'remaining'不會做同樣的事情,所以會有不同的結果。 –

+0

@ amanuel2你得到了類似的結果http://ideone.com/rLyS2t – umbersar

回答

3

你看到的問題是,你正在使用出現跟隨在cppreference規定實施的fmod版本:

double fmod(double x, double y) 
{ 
    double result = std::remainder(std::fabs(x), (y = std::fabs(y))); 
    if (std::signbit(result)) result += y; 
    return std::copysign(result, x); 
} 

std::remainder計算一個非常非常小的結果,幾乎爲零(-5.55112e -17使用1和0.1時,-1和-1.11022e-16代表2和0.2)。但重要的是,結果爲爲負,這意味着std::signbit返回true,導致y被添加到結果中,結果有效地等於y

注意的std::fmod文件並沒有說明使用std::remainder什麼:

此函數計算除法運算x/y的浮點餘數恰好是x的值 - N的* Y ,其中n是x/y,其小數部分被截斷。

所以,如果你自己計算的值,你最終獲得零(即使你對結果使用std::round,而不是純整數截斷)

我們看到了類似的問題時x是2和y是0.2

double x = 2; 
double y = .2; 

int n = static_cast<int>(x/y); 
double result = x - n*y; 
std::cout << "Manual: " << result << std::endl; 
std::cout << "fmod: " << std::fmod(x,y) << std::endl; 

輸出(gcc demo)是

手冊:0
FMOD:0.2

然而問題未降級到僅GCC;我也在MSVC和叮噹中看到它。在clang中,如果使用float而不是double,則有時會出現不同的行爲。

std::remainder這個非常小的負值來自這樣一個事實,即0.1和0.2都不能完全用浮點數學表示。如果您將x和y更改爲2和0.25,則一切正常。

+0

對於'fmod':*「正好是值x-n \ * y,其中n是x/y且其小數部分被截斷。」*和'int(x/h)== 10','n'應該是'10',因此'fmod(x,h)== 1 - 10 * .1'應該幾乎爲0.到目前爲止,您答案中的內容不足以解釋這一點。 –

+0

我剛剛在這裏發現了一個類似的問題.http://stackoverflow.com/q/26519082/364084。 – umbersar

+0

@AndyG我仍然按照這個解釋手動計算出結果。如果它解決了,我會將它標記爲答案 – umbersar