views:

1380

answers:

4

I have two simple while loops in my program that I feel ought to be math equations, but I'm struggling to convert them:

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

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

This code works as-is, but I feel it could be simplified into math equations. The idea here being that this code is taking an offset (someValue) and adjusting a coordinate (c) to minimize the distance from the center of a tile (of size someOtherValue). Any help would be appreciated.

+1  A: 

I think you want something like this:

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

That should match your loops except for certain cases where b is odd because the range from -b/2 to b/2 is smaller than b when b is odd.

Dave L.
"sin", not "sign", but yes, you want a sin wave function.
Ed Swangren
I think Dave really means sign(), defined by: int sign(x) { return x > 0 ? 1 : x < 0 ? -1 : 0; }
Greg Hewgill
Not correct: for a trivial example, take a = b = 10, then neither loop ever runs at all (so c=0) but this answer will say c=1.
ShreevatsaR
Shreevatsar: That's not true. If a = b = 10, then a >= b/2, so the later loop will run once, and c = 1.
Dave L.
Oh sorry, I wasn't thinking clearly. For a=b=10, this says c=((int) 10+5)/10, which is actually 1.5 :-) But if a and b are ints, so that "/" means integer division, then for positive a, it is floor(a+b/2)/b, so right, and for negative a it is ceil(a-b/2)/b=floor((a+b/2)/b) *except* when b|(a-b/2).
ShreevatsaR
That is, pick negative a such that it is b/2 mod b, e.g. b=10 and a=-5. Then c=-1+1=0, but ((int)-5-5)/10 is -1. But yeah, this is correct except when a is negative and b divides a-b/2; sorry for my first comment.
ShreevatsaR
BTW, if I may ask: how did you think of this? It seems something quite clever, and completely different from the others.
ShreevatsaR
+1  A: 

Assuming b is positive, abs(c) = floor((abs(a) - b/2) / b). Then, apply sign of a to c.

buti-oxa
+3  A: 
c = (int)((a - (b / 2)) / b + 1);
a -= c * b;

Test case at http://pastebin.com/m1034e639

paranoidgeek
It seems to work for positive a, but not negative.
Sydius
Using floor instead of dropping the decimal portion by converting it to an integer makes it work for negative values.
Sydius
+31  A: 
ShreevatsaR
Excellent answer. It works perfectly, though I will need to read it a few times to understand it fully.
Sydius
thanks for that long explanation!
Georg
My pleasure :) Actually I guess it could be a bit simpler... I just wrote it the way I first worked it out. If something is confusing, please point it out and I'll take another look at it.
ShreevatsaR