在m次迭代中平均间隔n个项目

时间:2019-01-06 22:41:15

标签: algorithm loops math

在上下文中,这是为了在高精度应用中同时控制多个步进电机。

问题陈述
假设我有一个循环,它将运行i个迭代。在这些迭代过程中,表达式E_x的计算结果应为true x倍(保证x <= i)。

要求
-E_x的计算结果必须为true准确 x
-E_x必须以或多或少均匀分布的间隔求值true *

*“间隔均匀”表示最大间隔尺寸已减小

示例
适用于:i = 10x = 7
E_x在标记为1的迭代中为true:1101101101

针对:i = 10x = 3
E_x在标记为1的迭代中为true:0010010010

针对:i = 10x = 2
E_x在标记为1的迭代中为true:0001000100

E_x在均匀间隔下求true的同时评估x次的真实性的最佳(甚至是“好的”)方法是什么?

This question离我很近,但是假设E_x在第一个和最后一个迭代中总会得出true,这不符合我的要求(请参见上面的第二个示例)

2 个答案:

答案 0 :(得分:0)

我将使用一些不同的命名约定:让我们以require.context个间隔T[1..T]个事件来触发。另外,让我们以循环的方式解决问题。为此,让我们在保证触发事件的末尾添加一个假步骤(这也是在时间0,即循环之前的事件)。因此,我的N是您的T,而我的i+1是您的N

如果将x+1除以T除以提醒,您将得到N。如果T = w*N + r,则情况不重要。如果r=0可以达到的最佳效果是r != 0个间隔为r的间隔和w+1个间隔为(N-r)的间隔。快速,简单但足够好的解决方案是这样的(伪代码):

w

您可以看到数组中的最后一个值将是events = [] w = T / N r = T % N current = 0 for(i = 1; i<=N; i++) { current += w; if (i <= r) current += 1; events[i] = current; } ,正如我们作为循环问题的重述所保证的那样。之所以为T,是因为在整个周期中,我们将Tw相乘current次,并向N相加r次,因此总和将是1,即w*N+r

此解决方案的主要缺点是,所有“长”间隔都将在开始时,而所有“短”间隔都将在结束时。

如果您比较聪明,则可以更均匀地分布时间间隔。结果逻辑与注释中引用的Bresenham's line algorithm后面的逻辑基本相同。假设您在平面上画一条线,其中T轴表示时间,X轴表示事件,来自Y(第(0,0)个事件,在您的时间范围之前)到0(这是第(i+1, x+1)个事件,紧随您的时间范围之后)。引发事件的时刻是当您切换到下一个x+1时,即在给定的Y处绘制第一个像素。

答案 1 :(得分:0)

如果您想在x次迭代中进行n次递增,则可以这样做:

int incCount = 0;
int iterCount = 0;

boolean step() {
    ++iterCount;
    int nextCount = (iterCount*x + n/2) / n; // this is rounding division
    if (nextCount > incCount) {
        ++incCount;
        return true;
    }
    else {
        return false;
    }
}

这是易于理解的方式。如果您使用的嵌入式CPU的划分成本更高,则可以完全一样地完成 这样的事情:

int accum = n/2;

boolean step() {
    accum+=x;
    if (accum >= n) {
        accum-=n;
        return true;
    }
    else {
        return false;
    }
}

与第一个示例一样,此处添加到accum的总金额为iterCount*x + n/2,但是该除法被增量重复减法所代替。这就是布雷森纳姆(Bresenham)的线条绘制算法的工作方式。