GCC mod() 定义

Juh*_*a P 1 c++ gcc function

我正在使用 GCC 在 C++ 中制作更快的 mod(x,2) 函数(使用 -O3 -ffast-math 编译),并发现 GCC 和 Octave 之间的结果存在差异:

float fast_fmod2(float x){ // over 50x faster than std::fmod(x, 2.0f)
    x *= 0.5f;
    return 2.0f * ( x - std::floor(x));
}
Run Code Online (Sandbox Code Playgroud)

结果(mod(输入,2.0f)):

Input       : -7.8539786 
std::fmod()  : -1.853978633881
Octave mod(): 0.146021366119
fast_fmod2  : 0.146021366119
...
Input       : 7.8539805
std::fmod()  : 1.853980541229
Octave mod(): 1.853980541229
fast_fmod2  : 1.853980541229
Run Code Online (Sandbox Code Playgroud)

我还检查了其他几个数学软件,看起来至少 Sollya 和 Wolfram|Alpha 支持 Octave 结果,并且之前提到的记录了与 Octave 相同的函数定义。

GCC将 mod 函数定义为:

mod(A, P) = A - (int(A/P) * P)
Run Code Online (Sandbox Code Playgroud)

SollyaOctave定义为:

mod(a, b) = a - (b * floor(a / b))
Run Code Online (Sandbox Code Playgroud)

由于 int(a/b) 与 Floor(a/b) 的舍入方式不同,GCC 定义对负 A 给出了不同的答案。

>> int16(-2.19/2)
ans = -1
>> floor(-2.19/2)
ans = -2
Run Code Online (Sandbox Code Playgroud)

这是 GCC 版本中的错误还是差异背后的其他原因?

Tur*_*ght 5

我假设你的意思std:fmod是代替(官方 C++ 标准中std::mod没有)std::mod

\n

造成这种差异的原因是std::fmod它的作用与您想象的不同。

\n

std::fmod计算余数而不是算术模数。

\n
\n

计算除法运算的浮点余数x/y

\n
\n

如果您想要算术模数,则需要使用std::remainder

\n
\n

计算浮点除法运算的 IEEE 余数x/ y。\n此函数计算出的除法运算的 IEEE 浮点余数x/y恰好是值x - n*y,其中该值n是最接近精确值 的整数值x/y。当 时|n-x/y| = \xc2\xbd,该值n被选择为偶数。

\n
\n

这将在您的示例中产生预期结果:

\n
std::cout << std::remainder(-7.8539786f, 2.0f) << std::endl; // 0.146021\n
Run Code Online (Sandbox Code Playgroud)\n

神箭示例

\n
\n

所以回答你的问题:这不是一个错误,这是有意的行为。
\n这些函数只是在 C++ 中以不同的方式命名(尽管命名方案有点令人困惑)

\n\n