C/C++ 中 fmod 函数的正确实现是:
#include <iostream>
using namespace std;
#include <math.h> //for trunc()
double MyFmod(double x, double y) {
return x - trunc(x / y) * y;
}
//test it
int main()
{
double values[13] = {-10.9, -10.5, -10.4, -0.9, -0.5, -0.1, 0, 0.1, 0.5, 0.9, 10.4, 10.5, 10.9};
for (size_t i = 0; i < 12; ++i)
cout << fmod(values[i], 3.0) <<" "<< MyFmod(values[i], 3.0) << endl;
for (size_t i = 0; i < 12; ++i)
cout << fmod(values[i], -3.0) <<" "<< MyFmod(values[i], -3.0) << endl;
return 0;
}
Java 中 fmod 函数的正确实现是:
//trunc() implementation in Java:
double truncate(double x) {
return x < 0 ? -Math.floor(-x) : Math.floor(x);
//or return x < 0 ? Math.ceil(x) : Math.floor(x);
}
double MyFmod(double x, double y) {
return x - truncate(x / y) * y;
}
还可以使用 fma 指令来提高精度(尽管只有在准确计算 trunc(x/y) 的结果时这才能正确工作):
C/C++: fma(trunc(x / y), -y, x);
Java: Math.fma(truncate(x / y), -y, x);
注意:当 double 的精度不够时,上述所有实现都可能不如编译器的数学库。在我的编译器中,std::fmod(1e19, 3) 计算 1.0(准确的结果),而具有相同参数的 MyFmod 返回 -512。