1

可能重复:
为什么“for( i = 0.1 ; i != 1.0 ; i += 0.1)” 不会在 i = 1.0 处中断?

我有一个数字(实数)区间 [x, y]。我必须使用类似的东西遍历它:

nr = 0;
for (i = x; i <= y; i += step) //step is a small double value
    nr++;

对于步长为 0.001 的 [-1, 1],很明显 nr 应该是 2001(-1.000 ... 0.999 1.000),但是它计算出 nr = 2000(我进行了调查,但最后一次比较失败:0.999 + 0.001 > 1.000)

如何计算准确的 nr 值?

4

4 回答 4

3

您需要使用整数来执行此操作,或者对不精确感到满意,因为浮点数和双精度数本质上是不精确的*。您的代码完全按照 C 语言规范工作。在需要精确精度的情况下使用浮点数和双精度数是不安全的。

除此之外,您需要在问题中提供有关您的要求的更多信息。如果nr是温度,那么要计算您需要使用不存在或不存在的物理学的确切值(我不是物理学家,所以我不能告诉你)。如果step实际上是一个不合理的值,那么您必须向上或向下舍入-您的调用以及正确的调用取决于您的业务逻辑要求。如果它是合理的并且不需要四舍五入,那么您需要乘以最小公分母并使用ints (或 C 中的分数类等)。

*当分数的分母是 2 的幂时,每条评论的浮点数/双精度数是精确的,如果你可以强制stepy遵守这一点,你的问题就会很清楚,但当然,如果step不均匀划分y,你需要做与上面完全相同的业务逻辑处理。

于 2012-12-06T20:09:12.150 回答
0

您遇到的问题是浮点数 (floatdouble) 没有准确存储,因此内存中的表示往往比不准确。

所以你有两个选择——使用精确的数字或​​使用整数作为循环的次数,然后计算值。

这可以按如下方式完成:

int numberOfIntervals = 2000;
double lowestValue = -1.0;
for (loop = 0; loop <= numberOfIntervals; ++loop)
{
    double v = (0.001 * loop ) + lowestValue;
}
于 2012-12-06T20:12:08.240 回答
0
int nsteps = (int)((y-x)/step);
for(int i=0; nsteps; ++i){
   double v = x + (i*step);  // use v in your calculations
}
于 2012-12-06T20:12:31.403 回答
-1

二进制浮点不精确是不正确的。正确的是,对于内容符合 2 的不同(正和/或负)幂之和的数字,该值将是精确的。显然,十进制数符合十的幂的总和,所以它们不会是精确的。以四、八和十六为底是一致的,因为它们是二的倍数。

我很久以前发布了这个答案,它会给你一个关于浮点数有多精确的提示。您还可以通过将 2 的负幂求和来查看分数如何组合。

至于如何解决问题,您拥有所需的工具。如果算法不适合,您可以使其适合。

于 2012-12-06T20:32:26.543 回答