3

我想就如何优化以下 while 循环提出一些建议:

double minor_interval   = 0.1;
double major_interval   = 1.0;

double start            = 0.0;
double finish           = 10.0;

printf("Start\r\n");

while (start < finish)
{
    printf("Minor interval: %.20f\r\n", start);

    double m = fmod(start, major_interval);
    printf("m: %.20f\r\n", m);

    if (m == 0)
        printf("At major interval: %.20f\r\n", start);

    start += minor_interval;
}

printf("Finished\r\n");

本质上,我将循环中的计数器增加了次要间隔,并且想知道每次循环中我是否处于主要间隔。把它想象成画一个以毫米为间隔的尺子,每次我到达一个主要的间隔时,我都想画一个厘米。考虑到浮点运算的不准确性,如何修改上述循环以实现我需要的功能?我尝试了不同的方法来比较模数的结果,但没有运气。请注意,次要和主要间隔可以是任何值,即次要 = 0.4 和主要 = 1.6(绘制四分之一英里增量)。

提前致谢。

4

3 回答 3

6

我会在一个int变量上使用 for 循环来实现这一点i。由于浮点运算的限制,使用整数可以避免舍入问题。[查看每个计算机科学家应该了解的关于浮点运算的知识。]

i0to运行iFinish-1并设置timestart + i*minor_interval。的值iFinish可以通过四舍五入(finish-start)/minor_interval到最接近的 int 来找到。

可以以类似的方式处理主轴更新。四舍五入major_interval/minor_intervalintk。然后每 k 次迭代更新主轴标记。

就代码而言,它看起来像这样:

double round(double r) {
    return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5);
}
...
int iFinish = round((finish-start)/minor_interval);
int k = round(major_interval/minor_interval);
for (int i=0; i<iFinish; i++)
{
    double time = start + i*minor_interval;
    bool isMajor = (i%k == 0);
    ...
}
于 2011-08-28T07:34:40.170 回答
0

您的容忍方法不起作用的原因是它只考虑存储值略高于应有的值。(例如,当它是 1.0001 而不是 1。如果它是 0.999 而不是 1,那么您的方法将不起作用)

要解决此问题,请检查它是否在预期值一侧的容差范围内。

所以,而不是:

if (m == 0)

采用:

if (m < small_value || major_interval - m < small_value)

其中 small_value 类似于 1e-8。

于 2011-08-28T07:45:40.767 回答
0

我会让循环成为使用整数的 for 循环。此外,由于这些类型的不精确性质,如果数字,您应该避免 == 运算符用于浮点数/双精度数。

因此,为了循环的目的,将双精度数转换为整数:

numIntervals = (int)((finish - start) / minor_intervals);
majIntervalsGap = numIntervals  / (int)((finish - start) / major_intervals);
double time = start;
for (int loop = 0;; loop < numIntervals; ++loop)
{
    bool isMajor = ((loop % majIntervalsGap) == 0);

    ... do you ourput here as you have the desired info for it
    time += minor_interval;
}
于 2011-08-28T08:29:56.797 回答