2016-10-10 66 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