实施FMOD功能

Ale*_*dre 3 c

fmod功能如何实施?

我尝试了以下方法:

#include <stdio.h>
#include <math.h>

float floatMod(float a, float b)
{
  return (a/b - floor(a/b));
}

int main()
{
  printf("%f\n", fmod(18.5,4.2));
  printf("%f\n", floatMod(18.5,4.2));
}
Run Code Online (Sandbox Code Playgroud)

但输出不一样......

Pau*_*l R 7

你的fmod功能应该是:

float floatMod(float a, float b)
{
    return (a - b * floor(a / b));
}
Run Code Online (Sandbox Code Playgroud)

LIVE DEMO

  • 这*可能*有效(我还不相信),但它需要一个重要的论点。正确的 `fmod` 是一个精确的操作,原则上你的实现有 3 个操作,它们可能会在 `floor` 中执行超出所需舍入的额外舍入。 (2认同)

0kc*_*ats 5

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;
}
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

还可以使用 fma 指令来提高精度(尽管只有在准确计算 trunc(x/y) 的结果时这才能正确工作):

C/C++: fma(trunc(x / y), -y, x);

Java: Math.fma(truncate(x / y), -y, x);
Run Code Online (Sandbox Code Playgroud)

注意:当 double 的精度不够时,上述所有实现都可能不如编译器的数学库。在我的编译器中,std::fmod(1e19, 3) 计算 1.0(准确的结果),而具有相同参数的 MyFmod 返回 -512。