Easy way to keeping angles between -179 and 180 degrees

后端 未结 16 2652
长发绾君心
长发绾君心 2020-12-04 16:41

Is there an easy way to convert an angle (in degrees) to be between -179 and 180? I\'m sure I could use mod (%) and some if statements, but it gets ugly:


/         


        
相关标签:
16条回答
  • 2020-12-04 17:15

    This works with both negative and decimal numbers and doesn't require loops, nor trigonometric functions:

    angle -= Math.floor(angle / 360 + 0.5) * 360

    The result is in the [-180, 180) interval. For (-180, 180] interval, you can use this instead:

    angle -= Math.ceil(angle / 360 - 0.5) * 360

    0 讨论(0)
  • 2020-12-04 17:15

    I don't know much Java, but I came across the same problem in Python. Most of the answers here were either for integers so I figured I'd add one that allows for floats.

    def half_angle(degree):
        return -((180 - degree) % 360) + 180
    

    Based off the other answers I'm guessing the function would looks something like this in Java (feel free to correct me)

    int halfAngle(int degree) {
        return -Math.floorMod(180 - degree, 360) + 180
    }
    
    double halfAngle(double degree) {
        // Java doesn't have a built-in modulus operator
        // And Math.floorMod only works on integers and longs
        // But we can use ((x%n) + n)%n to obtain the modulus for float
        return -(((180 - degree) % 360 + 360) % 360) + 180
    }
    

    Replace int with float to your liking.

    This works for any degree, both positive and negative and floats and integers:

    half_angle(180) == 180
    half_angle(180.1) == -179.9  // actually -179.89999999999998
    half_angle(-179.9) == -179.9
    half_angle(-180) = 180
    half_angle(1) = 1
    half_angle(0) = 0
    half_angle(-1) = -1
    

    Math explanation:

    Because the modulo operator is open at the upper end, the value x % 360 is in the range [0, 360), so by using the negative angle, the upper end becomes the lower end. So -(-x%360) is in (-360, 0], and -(-x%360)+360 is in (0, 360].

    Shifting this by 180 gives us the answer.

    0 讨论(0)
  • 2020-12-04 17:21

    I'm a little late to the party, I know, but...

    Most of these answers are no good, because they try to be clever and concise and then don't take care of edge cases.

    It's a little more verbose, but if you want to make it work, just put in the logic to make it work. Don't try to be clever.

    int normalizeAngle(int angle)
    {
        int newAngle = angle;
        while (newAngle <= -180) newAngle += 360;
        while (newAngle > 180) newAngle -= 360;
        return newAngle;
    }
    

    This works and is reasonably clean and simple, without trying to be fancy. Note that only zero or one of the while loops can ever be run.

    0 讨论(0)
  • 2020-12-04 17:21

    Here is an integer-only solution:

    int normalize(int angle)
    {
        angle %= 360;
        int fix = angle / 180; // Integer division!!
        return (fix) ? angle - (360 * (fix)) : angle;
    }
    

    Sometimes being clever is just more fun, Platinum Azure.

    0 讨论(0)
  • 2020-12-04 17:22

    Not that smart, too, but no if.

    angle = (angle + 179) % 360 - 179;

    But I am not sure how Java handles modulo for negative numbers. This works only if -1 modulo 360 equals 359.

    UPDATE

    Just checked the docs and a % b yields a value between -(|b| - 1) and +(|b| - 1) hence the code is broken. To account for negative values returned by the modulo operator one has to use the following.

    angle = ((angle + 179) % 360 + 360) % 360 - 179;
    

    But ... no ... never ... Use something similar to your initial solution, but fixed for values smaller then -179.

    0 讨论(0)
  • 2020-12-04 17:25

    I know that years have passed, but still.

    This solution contains no loops, no subtracting, no modulo (allows to normalize to radians interval). Works for any input, including negative values, big values, edge cases.

    double normalizedAngle = angle - (ceil((angle + M_PI)/(2*M_PI))-1)*2*M_PI;  // (-Pi;Pi]:
    double normalizedAngle = angle - (ceil((angle + 180)/360)-1)*360;           // (-180;180]:
    
    double normalizedAngle = angle - (floor((angle + M_PI)/(2*M_PI)))*2*M_PI;  // [-Pi;Pi):
    double normalizedAngle = angle - (floor((angle + 180)/360))*360;           // [-180;180):
    
    0 讨论(0)
提交回复
热议问题