输出fmod函数c ++ [英] output of fmod function c++

查看:491
本文介绍了输出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,但我得到的是.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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆