给定以下双打,是否fmod
返回正确的值?
double x = .090;
double y = .003;
double r = fmod(x, y);
// r = 0.0029999999999999949
为什么 r = 0?
给定以下双打,是否fmod
返回正确的值?
double x = .090;
double y = .003;
double r = fmod(x, y);
// r = 0.0029999999999999949
为什么 r = 0?
因为,像大多数小数一样,这些数字不能用二进制浮点格式精确表示。要查看实际使用的值:
#include <cstdio>
int main() {
printf("%.20f %.20f\n", .090, .003);
}
Output: 0.08999999999999999667 0.00300000000000000006
这些小的舍入误差意味着第一个值略小于第二个值的精确倍数,因此您会看到结果。
您可能希望允许对错误有一个小的容忍度:
if (r > y - some_small_value) {
r = 0;
}
这类问题可以通过阅读一篇题为What Every Computer Scientist Should Know About Floating-Point Arithmetic的论文来解决。
你的机器对浮点数使用二进制表示,它不能精确地表示有理数 3/1000 = 0.003。
当然,机器可以将 0.003 的近似值打印为"0.003"
,但这是通过内部格式化的打印代码完成的printf
,当它将值四舍五入为给定的小数位数时。
浮点值的打印十进制版本与其实际内部值之间的差异可能会给不了解这些问题的程序员或用户带来问题。