把while循环变成数学方程式?

时间:2008-12-25 00:12:44

标签: c++ c algorithm math

我的程序中有两个简单的while循环,我觉得应该是数学方程式,但我很难转换它们:

float a = someValue;
int b = someOtherValue;
int c = 0;

while (a <= -b / 2) {
    c--;
    a += b;
}
while (a >= b / 2) {
    c++;
    a -= b;
}

此代码按原样运行,但我觉得它可以简化为数学方程式。这里的想法是这个代码采用偏移量(someValue)并调整坐标(c)以最小化距瓷砖中心的距离(大小为someOtherValue)。任何帮助将不胜感激。

4 个答案:

答案 0 :(得分:36)

可以证明以下是正确的:

c = floor((a+b/2)/b)
a = a - c*b

请注意,floor表示向下舍入,向负无穷大:不向0(例如floor(-3.1)= - 4. floor()库函数将执行此操作;请确保不要仅转换为int ,通常会向0舍入。)

可能b严格为正,因为否则两个循环都不会终止:添加b不会使a变大,减去b也不会a小一点。有了这个假设,我们可以证明上面的代码是有效的。 (并且paranoidgeek的代码也几乎是正确的,除了它使用转换为int而不是floor。)

明智的证明方式: 代码在b中添加或减去a的倍数,直到a [-b/2,b/2)a/b,您可以在a/b中查看添加或减去整数 {1}} [-1/2,1/2)(a/b+1/2)之前,x(称之为[0,1))在x之前{1}}。由于您只是按整数更改它,mod 1的值不会更改x-floor(x),即它会转到余数mod 1 ,即c。因此,您所做的有效减法次数(floor(x))为c

证明它的繁琐方式

<子> 在第一个循环结束时,x = (a+b/2)/b的值是循环运行次数的负数,即:

  • 0 if:a&gt; -b / 2&lt; =&gt; a + b / 2> 0
  • -1 if:-b /2≥a> -3b / 2&lt; =&gt; 0≥a+ b / 2> -b&lt; =&gt; 0≥x> 0 -1
  • -2 if:-3b /2≥a> -5b / 2&lt; =&gt; -b≥a+ b / 2> -2b&lt; =&gt; -1≥x> -2等,

其中x,所以c是:如果x> 0则为0,否则为“ceiling(x)-1”。如果第一个循环完全运行,那么在最后一次循环执行之前它是≤-b / 2,所以现在≤-b / 2 + b,即≤b/ 2 。根据它是否正好是b / 2(即,当你开始时是y = (a-b/2)/b是否是一个非正整数),第二个循环恰好运行1次或0,c是天花板( x)或ceiling(x)-1。所以这解决了第一个循环运行时的情况。

如果第一个循环没有运行,那么第二个循环结束时c的值为:

  • 0如果:a&lt; b / 2&lt; =&gt; a-b / 2&lt; 0
  • 1 if:b /2≤a<1。 3b / 2&lt; =&gt; 0≤a-b / 2&lt; b&lt; =&gt; 0≤y<0。 1
  • 2 if:3b /2≤a&lt; 5b / 2&lt; =&gt; b≤a-b / 2&lt; 2b&lt; =&gt; 1≤y<1。 2等,

其中a,所以c为:如果y <0则为0,否则为1 + floor(y)。 [而c现在肯定是&lt; b / 2且≥-b / 2.]

因此,您可以将x = (a+b/2)/b y = (a-b/2)/b c = (x≤0)*(ceiling(x) - 1 + (x is integer)) +(y≥0)*(1 + floor(y)) 的表达式编写为:

(ceiling(x)-1+(x is integer))

当然,接下来您注意到floor(x+1)-1floor(x)相同,y,而x-1实际上是(1+floor(y))=floor(x),所以{{1和条件:
当x≤0时,它不能是(y≥0),因此c只是floor(x)的第一项, 当0 < x&lt; 1,这两个条件都不成立,因此c0
当1≤x时,则只有0≤y,所以c再次是floor(x)的第二项。 所以c = floor(x)

答案 1 :(得分:2)

c = (int)((a - (b / 2)) / b + 1);
a -= c * b;

http://pastebin.com/m1034e639

的测试用例

答案 2 :(得分:1)

我想你想要这样的东西:

c = ((int) a + b / 2 * sign(a)) / b

那应该匹配你的循环,除了某些情况,其中b是奇数,因为当b是奇数时,-b / 2到b / 2的范围小于b。

答案 3 :(得分:0)

假设b为正,则abs(c)= floor((abs(a)-b / 2)/ b)。然后,将a的符号应用于c。