在上下文中,这是为了在高精度应用中同时控制多个步进电机。
问题陈述
假设我有一个循环,它将运行i
个迭代。在这些迭代过程中,表达式E_x
的计算结果应为true
x
倍(保证x <= i
)。
要求
-E_x
的计算结果必须为true
准确 x
次
-E_x
必须以或多或少均匀分布的间隔求值true
*
*“间隔均匀”表示最大间隔尺寸已减小
示例
适用于:i = 10
,x = 7
E_x
在标记为1
的迭代中为true:1101101101
针对:i = 10
,x = 3
E_x
在标记为1
的迭代中为true:0010010010
针对:i = 10
,x = 2
E_x
在标记为1
的迭代中为true:0001000100
让E_x
在均匀间隔下求true
的同时评估x
次的真实性的最佳(甚至是“好的”)方法是什么?>
This question离我很近,但是假设E_x
在第一个和最后一个迭代中总会得出true
,这不符合我的要求(请参见上面的第二个示例)
答案 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
,是因为在整个周期中,我们将T
与w
相乘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)的线条绘制算法的工作方式。