This question already has answers here:
Closed 4 years ago.
Is floating point math broken?
(31个答案)
我有以下代码:
这是一段与我必须做的项目隔离的代码。最终结果应该是255000,但由于某些原因,它显示254999。有人能解释一下这个过程中发生了什么吗?我在某个地方读到过,把一个浮点数乘以10^k,然后再除以就解决了这样的问题,但是在这种情况下,由于变量步长在0.000001到0.1之间变化,我实际上不能使用它(同样地,我不能使用一个定义的EPSILON)。我还能做什么?
提前谢谢!
备注:我也使用了double和long double,但是同样的问题,只有这次错误会从一个小数点开始传播。我使用的是GCC4.8.2,在Ubuntu14.04.1下。
(31个答案)
我有以下代码:
#include<stdio.h>
int main(int argc, char const *argv[])
{
float min, max, step;
min = -0.85, max = 0.85, step = 0.002;
int rank = 3, total = 4;
float step1 = min + (max - min) * rank / total; // should be 0.425
printf("%f %.7g\n", step1, step1); // 0.425000 0.4250001
float step2 = min + (max - min) * (rank + 1) / total - step; //should be 0.848
printf("%f %.7g\n", step2, step2); // 0.848000 0.848
float noc = (step2 - step1 + step) / step; //should be 212,5
printf("%f %.7g\n", noc, noc); // 212.499985 212.5
int nol = 1200;
int result = (int)nol * noc; //should be 255000
printf("%d\n", result); // 254999
return 0;
}
这是一段与我必须做的项目隔离的代码。最终结果应该是255000,但由于某些原因,它显示254999。有人能解释一下这个过程中发生了什么吗?我在某个地方读到过,把一个浮点数乘以10^k,然后再除以就解决了这样的问题,但是在这种情况下,由于变量步长在0.000001到0.1之间变化,我实际上不能使用它(同样地,我不能使用一个定义的EPSILON)。我还能做什么?
提前谢谢!
备注:我也使用了double和long double,但是同样的问题,只有这次错误会从一个小数点开始传播。我使用的是GCC4.8.2,在Ubuntu14.04.1下。
最佳答案
截断与舍入。
由于FP算法的细微舍入效应,乘积nol * noc
可能略小于整数值。转换为int
将导致分数截断。建议在转换为int
之前进行舍入。
#include <math.h>
int result = (int) roundf(nol * noc);
关于c - 浮点数的C怪异近似,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27161488/
10-13 08:25