可能重复:
Why “for( i = 0.1 ; i != 1.0 ; i += 0.1)” doesn’t break at i = 1.0?
我有一个数字(实际)区间[x,y]。我必须使用类似的东西来迭代它:
nr = 0;
for (i = x; i <= y; i += step) //step is a small double value
nr++;
对于[-1,1],步长为0.001,很明显nr应该是2001(-1.000 ... 0.999 1.000),但它计算nr = 2000(我调查了它并且最后一次比较失败了:0.999 + 0.001 &gt; 1.000)
如何计算确切的nr值?
答案 0 :(得分:3)
你需要使用整数来做这件事,或者对不精确感到满意,因为浮点数和双打本身就是不精确的*。您的代码完全符合C语言规范。浮动和双打在要求精确精确的情况下使用是不安全的。
除此之外,您需要在问题中提供有关您的要求的更多信息。如果nr
是一个温度,那么计算你需要使用不存在或不存在的物理学的确切值(我不是物理学家,所以我不能告诉你)。如果step
实际上是一个非理性值,那么您必须向上或向下舍入 - 您的调用以及哪个是正确的取决于您的业务逻辑要求。如果它是合理的并且不需要舍入,则需要乘以最小公分母并使用int
s(或C中的分数类等)。
*每个注释浮点数/双精度数是准确的,当分数具有2的幂的分母时,如果你可以强制step
和y
符合这个,你的问题会很清楚,但是当然,如果step
未均匀分配到y
,您将需要执行与上述完全相同的业务逻辑处理。
答案 1 :(得分:0)
您遇到的问题是浮点数(float
或double
)没有完全存储,因此内存中的表示形式比不完全更准确。
所以你有两个选择 - 使用精确数字或在循环周围使用整数,然后计算值。
这可以按如下方式完成:
int numberOfIntervals = 2000;
double lowestValue = -1.0;
for (loop = 0; loop <= numberOfIntervals; ++loop)
{
double v = (0.001 * loop ) + lowestValue;
}
答案 2 :(得分:0)
int nsteps = (int)((y-x)/step);
for(int i=0; nsteps; ++i){
double v = x + (i*step); // use v in your calculations
}
答案 3 :(得分:-1)
二进制浮点不精确是不正确的。真实的是,对于内容符合两个不同(正和/或负)幂的总和的数字,该值将是精确的。显然,十进制数字符合十的幂的总和,因此它们不准确。基础四,八和十六符合,因为它们是两的倍数。
我很久以前发布了this answer,它会给你一个关于浮点数有多精确的提示。您还可以通过将两个负幂相加来查看分数的组合方式。
至于如何解决问题,您可以获得所需的工具。如果算法不合适,你可以使它适合。