As Marcel rightly points out, modulo on negative numbers is potentially problematic. Also, what is the difference between 355 and 5 degrees? It might be worked out to be 350 degrees but 10 degrees is probably what people are expecting. We make the following assumptions:
- we want the smallest positive angle between two other angles so
0 <= diff <= 180
; - we are working in degrees. If radians, substitute 360 for
2*PI
; - angles can be positive or negative can be outside the range
-360 < x < 360
where x is an input angle and - order of input angles or the direction of the difference is irrelevant.
Inputs: angles a and b. So the algorithm is simply:
- Normalize a and b to
0 <= x < 360
; - Compute the shortest angle between the two normal angles.
For the first step, to convert the angle to the desired range, there are two possibilities:
x >= 0
: normal = x % 360x < 0
: normal = (-x / 360 + 1) * 360 + x
The second is designed to remove any ambiguity on the difference in interpretation of negative modulus operations. So to give a worked example for x = -400:
-x / 360 + 1
= -(-400) / 360 + 1
= 400 / 360 + 1
= 1 + 1
= 2
then
normal = 2 * 360 + (-400)
= 320
so for inputs 10 and -400 the normal angles are 10 and 320.
Now we calculate the shortest angle between them. As a sanity check, the sum of those two angles must be 360. In this case the possibilities are 50 and 310 (draw it and you'll see this). To work these out:
normal1 = min(normal(a), normal(b))
normal2 = max(normal(a), normal(b))
angle1 = normal2 - normal1
angle2 = 360 + normal1 - normal2
So for our example:
normal1 = min(320, 10) = 10
normal2 = max(320, 10) = 320
angle1 = normal2 - normal1 = 320 - 10 = 310
angle2 = 360 + normal1 - normal2 = 360 + 10 - 320 = 50
You'll note normal1 + normal2 = 360
(and you can even prove this will be the case if you like).
Lastly:
diff = min(normal1, normal2)
or 50 in our case.