views:

88

answers:

4

Out of curiosity, is there a (language independent*) way to make these two generic statements into one statement?

if (a < b) a += x;
else if (a > b) a -= x;

May also be used as

if (abs(b - a) < x) a = b;
else if (a < b) a += x;
else if (a > b) a -= x;

Oh, now that I'm writing this I'm thinking of something like this:

if (a != b) a += x * (a < b ? 1 : -1);

But that doesn't really benefit the readability. Other ways perhaps?

  • = Normal languages, not Brainfuck and the likes or really ancient ones
A: 
a += (b - a) / abs(b - a) * x

But this is not language independent and does not really help readiness if you ask me....

Benoit Vidis
what happens if a = b?
fastcodejava
+1  A: 

Language independent is a bit tricky, but if you have cmp or similar, you can use that:

a += x * cmp(b, a)

cmp(b, a) returns:

  • 0 if b==a
  • 1 if b > a
  • -1 if a < b

Also, there is a bug in your suggested implementation:

a = 9;
b = 10;
x = 2;

if (a < b) a += x;
if (a > b) a -= x;

print a;

Output: 9 (expected 11)

You need an else to fix this. Alternatively, if you want to prevent a going past b, do this:

if (a < b)
{
   a = min(b, a + x);
}
else if (a > b)
{
   a = max(b, a - x);
}

If you want to do this in one expression you can:

a = (a < b) ? min(b, a + x) : max(b, a - x);

I think the first way is clearer though.

Mark Byers
Thanks, fixed the bug.
Bart van Heukelom
+3  A: 

You should really wonder why you want this, the compiler will do fine optimizing and the given statement is very readable.

Thirler
I didn't know the compiler will optimize this, good to know. Regarding readability, you are correct too, with the alternatives posted so far. I was just wondering if there is one that is shorter but just as readable.
Bart van Heukelom
+6  A: 
a += x * sgn(b-a)

Where sgn is the sign function:

sgn x | x > 0      = 1
      | x < 0      = -1
      | otherwise  = 0
jleedev
I know languages that don't have "sgn", and Haskell doesn't have assignment at all, let alone "+=" ;-)
Steve314
Well, Haskell has `signum` built in. I think I just designed this example to be unworkable in any language ;)
jleedev