views:

132

answers:

7

I often need this kind of function, for example, for understand the direction of the touches on iPhone and the only way to solve this problem it's by using logic, like this:

int dir,distY;
distY = newY-oldY;

if (distY > 0) 
{
    dir = 1;
}
else if (distY < 0) 
{
    dir = -1;
}

I would like to know if there is an way to do it in one shoot mybey by using a mathematical method or a fashion old-school way.

Clarification, a similar example of what I'm looking for is:

i = ++i % max;

instead of:

i++;
if ( i > max ) { i = 0; }
+1  A: 

direction = distY / abs(distY)

You will still need to check to make sure distY is not 0, though.

Dave Markle
"You will still need to check to make sure distY is not 0, though" -- no, the problem statement doesn't define any result when distY is 0 so a crash is perfectly acceptable :-)
Windows programmer
+2  A: 

If you know the value will be nonzero, you could just divide by the absolute value:

dir = distY / abs(distY);

If it could possibly be zero, and you still want to set the flag to something, you could do something like this (in C/C++):

dir = distY >= 0 ? 1 : -1;

This will set dir to 1 when distY is zero as well.

Amber
Keep in mind that if this is an attempt at optimization, smaller source code does not necessarily mean better, faster, smaller, or more efficient compiled code. As an example, a call to `abs()` and a divide is most likely slower than a pair of conditional-move instructions, and trying to be "tricky" can often end up just confusing the optimizer and producing less-optimized compiled code.
Anon.
So the solution is a convoluate method that can either have a divide by zero problem or requires the ternary operator, which is really just another if statement?
cletus
@cletus - really it's more of a "here are the options", because in reality, an `if`/`else` combo is pretty much the simplest way of doing it, if wordier.
Amber
+2  A: 

Assuming you're using something like C or C++ that will convert true to 1 and false to 0, you could use: direction = (distY > 0) - (distY < 0);. You didn't say what you wanted when distY=0 -- this gives 0 (which seems like the obvious choice to me, but who knows).

Of course, there's no guarantee it'll do any good -- that will depend on a combination of compiler, compiler flags, CPU, and maybe even the phase of the moon. OTOH, I'd guess it has more chance of doing good than harm anyway.

Jerry Coffin
A: 

If you insist on being terse, try

(i>0)?1:((i<0)?-1:0)

(assuming you want to cover the zero case in the most sensible way).

There may be hacks using shifts of the sign bit, but I doubt they'll be either elegant or efficient.

Personally, I'd use the if-else construct.

Don Roby
A: 

If you're using a language where 0 is false and 1 is true (or offers that type conversion), then in pseudo code:

i = abs(distY) == distY; // 0 or 1
i = i*2 - 1; // -1 or 1
Lèse majesté
A: 

You could probably tell me if there is something similar in C, but Perl has just the equality operator for the job.

The <=> operator would be used like so:

$dir = $distY <=> 0;

From the documentation (perldoc perlop):

Binary "<=>" returns -1, 0, or 1 depending on whether the left argument is numerically less than, equal to, or greater than the right argument.

Now what I'd like to know is if something similar exists in C, C++ and/or Objective-C.

Zaid
+1  A: 

It seems you are looking for the signum function. If your programming language/libraries do not have it it's pretty easy to write: just wrap your if/else statements in a function so it will be easier and nicer to use.

With mathematical notations:
sign(n) =
|-1 if n < 0
| 0 if n = 0
| 1 if n > 0

If it is slower or faster then bit manipulation depends on the language, the target platform and on the library (if you use one). Involving abs in any way (as recommended in some answers) is probably an overkill, as it will internally contain pretty much the same logic, and you have some one more call and a division + you have to deal with potential division by zero.

Sandor Murakozi