为什么我得到的结果与std::fmod和std::remains不同

Why am I getting a different result from std::fmod and std::remainder

本文关键字:std fmod remains 不同 结果 为什么      更新时间:2023-10-16

在下面的示例应用程序中,我使用std::fmod 计算953除以0.1的浮点余数

我所期待的是,自953.0 / 0.1 == 9530以来,std::fmod(953, 0.1) == 0

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

注意,使用std::remainder,我得到了正确的结果。

即:

std::fmod     (953, 0.1) == 0.1 // unexpected
std::remainder(953, 0.1) == 0   // expected

两种功能之间的区别:

根据cppreference.com

  • std::fmod计算如下:

恰好是值x - n*y,其中n是其分数部分截断的x/y

  • std::remainder计算如下:

精确的值x - n*y,其中n是最接近精确值x/y 的整数值

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

示例应用程序:

#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

因为它们是不同的函数。

std::remainder(x, y)计算IEEE余数,其为x - (round(x/y)*y),其中round将半舍入为偶数(因此特别是round(1.0/2.0) == 0

CCD_ 20计算CCD_。当你用953除以0.1时,你可能会得到一个略小于9530的数字,所以截断得到9529。因此,您得到953.0 - 952.9 = 0.1

欢迎使用浮点数学。事情是这样的:十分之一不能用二进制精确表示,就像三分之一不能用十进制精确表示一样。因此,除法产生的结果略低于9530。楼层运算产生整数9529,而不是9530。然后剩下0.1。