输出fmod函数c ++ [英] output of fmod function 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,但我得到的是.0999999999。这是一个显着的差异。 remainder()的结果仍然可以接受。您可以在 http://ideone.com/9wBlva 尝试使用验证码
Given int(x/h) == 10
, I would have expected the fmod()
result to be near 0 but what i get is .0999999999. It is a significant difference. The result of remainder() still seem acceptable. Code could be tried at http://ideone.com/9wBlva
为什么fmod()结果的显着差异?
Why this significant difference for fmod() result?
推荐答案
fmod
您正在使用似乎遵循在 cppreference :
The problem you're seeing is that the version of fmod
you're using appears to follow the implementation defined at cppreference:
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
计算非常非常小的结果,几乎为零(当我使用1和0.1时,-5.55112e-17,对于2和0.2使用-1.11022e-16)。但是,重要的是结果是否定,这意味着 std :: signbit
返回true,导致 y
添加到结果中,结果等于 y
。
std::remainder
computes a very very small result, nearly zero (-5.55112e-17 when using 1 and 0.1 for me, -1.11022e-16 for 2 and 0.2). However, what's important is that the result is negative, which means std::signbit
returns true, causing y
to get added to the result, effectively making the result equal to y
.
请注意 std :: fmod
没有说明使用
std :: remainder
:
由此函数计算的除法运算x / y的浮点余数正好是值x-n * y,其中n是x / y,其小数部分被截断。
The floating-point remainder of the division operation x/y calculated by this function is exactly the value x - n*y, where n is x/y with its fractional part truncated.
所以如果你自己计算的值,你最终以零(即使你使用 std :: round
结果而不是纯整数截断)
So if you compute the value yourself, you do end up with zero (even if you use std::round
on the result instead of pure integer truncation)
当 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
Manual: 0
fmod: 0.2
但是问题并没有降级为gcc;我也看到它在MSVC和铛。在clang中,如果使用 float
而不是 double
,有时会有不同的行为。
However the problem is not relegated to only gcc; I also see it in MSVC and clang. In clang there is sometimes different behavior if one uses float
instead of double
.
来自 std :: remainder
的真正小的负值来自这样的事实,即0.1和0.2都不能在浮点数学中精确表示。如果你改变x和y,比如说2和0.25,那么一切都很好。
This really small negative value from std::remainder
comes from the fact that neither 0.1 nor 0.2 can be represented exactly in floating point math. If you change x and y to, say 2 and 0.25, then all is well.
这篇关于输出fmod函数c ++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!