我的程序中有两个简单的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大小)的距离。任何帮助,将不胜感激。

最佳答案

可以证明以下是正确的:

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/2,1/2)中为止,即直到(a/b+1/2)(称为x)在[0,1)中。由于您仅以整数进行更改,因此x的值不会更改mod 1,即转到其余数mod 1 ,即x-floor(x)。因此,您进行的减法有效次数(即c)为floor(x)

证明oyt_rstrong的繁琐方式:

在第一个循环结束时,c的值是循环运行次数的负数,即:
  • 0,如果:a> -b/2 a + b/2> 0
  • -1,如果:-b/2≥a> -3b/2 0≥a + b/2> -b 0≥x> -1
  • -2如果:-3b/2≥a> -5b/2 -b≥a + b/2> -2b -1≥x> -2等,

  • 其中x = (a+b/2)/b,所以c为:如果x> 0则为0,否则为“ceiling(x)-1”。如果第一个循环完全运行,那么它恰好在上一次执行循环之前≤-b/2,所以现在≤-b/2 + b,即≤b/2。根据是否恰好是b/2(即,启动时的x是否恰好是非正整数),第二个循环恰好运行1次或0,并且c是ceiling(x)或ceiling (x)-1。这样就解决了第一个循环确实运行的情况。

    如果第一个循环未运行,则第二个循环结束时c的值为:
  • 0如果:a
  • 1如果:b/2≤a
  • 2如果:3b/2≤a
    其中y = (a-b/2)/b,所以c为:如果y a现在肯定是
    因此,您可以将c的表达式编写为:
    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),并且对于条件句:
    当x≤0时,不能等于(y≥0),因此c只是第一个项floor(x)
    当0 为0
    当1≤x时,则只有0≤y,因此c只是第二项,它又是floor(x)
    所以在所有情况下c = floor(x)

    关于c++ - 将while循环转换成数学方程式?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/392375/

  • 10-12 15:34