C++ 为什么我从std::fmod和std::rements得到不同的结果

C++ 为什么我从std::fmod和std::rements得到不同的结果,c++,floating-point,C++,Floating Point,在下面的示例应用程序中,我使用std::fmod 我所期望的是,既然953.0/0.1==9530,那么std::fmod(953,0.1)==0 我得到了0.1-为什么会这样? 请注意,使用std::rements可以得到正确的结果 即: std::fmod (953, 0.1) == 0.1 // unexpected std::remainder(953, 0.1) == 0 // expected 两种功能之间的区别: 据 std::fmod计算如下: 正好是值x-n*

在下面的示例应用程序中,我使用
std::fmod

我所期望的是,既然
953.0/0.1==9530
,那么
std::fmod(953,0.1)==0

我得到了
0.1
-为什么会这样?

请注意,使用
std::rements
可以得到正确的结果

即:

std::fmod     (953, 0.1) == 0.1 // unexpected
std::remainder(953, 0.1) == 0   // expected
两种功能之间的区别: 据

  • std::fmod
    计算如下:
正好是值
x-n*y
,其中
n
x/y
,其小数部分被截断

  • std::余数
    计算如下:
精确值
x-n*y
,其中
n
是最接近精确值
x/y

考虑到我的输入,我希望两个函数具有相同的输出。为什么不是这样?

示例应用程序:
因为它们是不同的功能

计算哪个是
x-(四舍五入(x/y)*y)
其中
round
是(因此特别是
四舍五入(1.0/2.0)==0


计算
x-trunc(x/y)*y
。当你将
953
除以
0.1
时,你可能得到一个略小于9530的数字,因此截断得到9529。因此得到的结果是
953.0-952.9=0.1

欢迎使用浮点数学。事情是这样的:十分之一不能用二进制表示,正如三分之一不能用十进制表示一样。因此,该部门产生的结果略低于9530。floor操作生成整数9529而不是9530。然后剩下0.1。

他不明白的是为什么
fmod
返回0.1——你没有解释这一点。“std::余数(x,y)计算x-(舍入(x/y)*y)”-这是真的吗?例如,std::rements(1.0,2.0)是1.0,而(1.0-round(1.0/2.0)*2.0)是-1.0。这是用g++7.3.0实现的。@user2258552
round(1.0/2.0)==0
根据IEEE的定义(非常奇怪)-我编辑了我的答案以澄清这一点。谢谢你指出。那为什么
int(953/.1)==9530
?如果您的断言是正确的,那么是否也应该将其截断为
9529
。它解释了如果我们查看fmod()的文档,预期结果与实际结果之间的差异。这是由于在fmod()实现中使用了rements()。
#include <iostream>
#include <cmath>

bool is_zero(double in)
{
    return std::fabs(in) < 0.0000001;
}

int main()
{
    double numerator   = 953;
    double denominator = 0.1;

    double quotient = numerator / denominator;
    double fmod     = std::fmod     (numerator, denominator);
    double rem      = std::remainder(numerator, denominator);

    if (is_zero(fmod))
        fmod = 0;
    if (is_zero(rem))
        rem = 0;

    std::cout << "quotient: " << quotient << ", fmod: " << fmod << ", rem: " << rem << std::endl;
    return 0;
}
quotient: 9530, fmod: 0.1, rem: 0