首页 > 解决方案 > 在 C 中使用浮点数计算模数时出现问题

问题描述

我不是编程专家,我面临以下问题。

我需要计算浮点数 A 和 B 之间的模数。所以我使用 fmod((double)A, (double)B)。理论上,如果 A 是 B 的倍数,则结果为 0.0。但是,由于浮点精度的目的,A 和 B 并不是我期望的数字。然后,模计算的结果不是 0.0,而是不同的东西。这是有问题的。

示例:A=99999.9,但编译器将其解释为 99999.898。B=99.9,但编译器将其解释为 99.900002。fmod(A,B) 预计为 0.0,但实际上给出了 99.9。

所以问题是:你如何使用来管理这种情况?

谢谢

标签: cprecisionmodulo

解决方案


问题是:
Ais not 99999.9, but 99999.8984375 and
Bis not 99.9, but 99.90000152587890625 and
A mod B is 99.89691162109375

OP 正在为给出的论点得到正确的答案。

需要使用不同的增强。

一个合理的替代方法是将参数按比例缩放的 10 次方转换,然后舍入为整数, %,再返回浮点和不缩放。

溢出是一个问题。

由于 OP 想要将数字处理到最接近的 0.1,因此按 10 缩放。

#include <float.h>
#include <stdio.h>

int main(void) {
  float A = 99999.9;
  float B = 99.9;
  printf("%.25f\n", A);
  printf("%.25f\n", B);
  printf("%.25f\n", fmod(A,B));
  long long a = lround(A*10.0);
  long long b = lround(B*10.0);
  long long m = a%b;
  double D = m/10.0;
  printf("D = %.25f\n", D);
  return 0;
}

输出

99999.8984375000000000000000000
99.9000015258789062500000000
99.8969116210937500000000000
D = 0.0000000000000000000000000

选择

  long long a = lround(A*10.0);
  long long b = lround(B*10.0);
  long long m = a%b;
  double D = m/10.0;

缩放,但跳过整数转换部分

  double a = round(A*10.0);
  double b = round(B*10.0);
  double m = fmod(a,b);
  double D = m/10.0;

推荐阅读