Java 将角度保持在 -179 到 180 度之间的简单方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2320986/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 06:06:57  来源:igfitidea点击:

Easy way to keeping angles between -179 and 180 degrees

javamath

提问by User1

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:

是否有一种简单的方法可以将角度(以度为单位)转换为 -179 和 180 之间?我确定我可以使用 mod (%) 和一些 if 语句,但它变得丑陋:


//Make angle between 0 and 360
angle%=360;

//Make angle between -179 and 180
if (angle>180) angle-=360;

It just seems like there should be a simple math operation that will do both statements at the same time. I may just have to create a static method for the conversion for now.

似乎应该有一个简单的数学运算可以同时执行两个语句。我现在可能只需要为转换创建一个静态方法。

采纳答案by Platinum Azure

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.

这有效并且相当干净和简单,而不是试图花哨。请注意,只能运行零个或一个 while 循环。

回答by Daniel Brückner

Not that smart, too, but no if.

也不是那么聪明,但没有如果。

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

角度 = (角度 + 179) % 360 - 179;

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

但我不确定 Java 如何处理负数的模数。这仅在 -1 模 360 等于 359 时有效。

UPDATE

更新

Just checked the docs and a % byields 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.

刚刚检查了文档并a % b产生了一个介于两者之间的值-(|b| - 1)+(|b| - 1)因此代码被破坏了。为了说明模运算符返回的负值,必须使用以下内容。

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

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

但是......不......从不......使用类似于您的初始解决方案的东西,但固定值小于-179。

回答by pkaeding

How about

怎么样

(angle % 360) - 179

This will actually return different results than the naive approach presented in the question, but it will keep the angle between the bounds specified. (I suppose that might make this the wrong answer, but I will leave it here in case it solves another persons' similar problem).

这实际上将返回与问题中提出的幼稚方法不同的结果,但它会保持指定边界之间的角度。(我想这可能会使这成为错误的答案,但我会把它留在这里,以防它解决其他人的类似问题)。

回答by Steve314

Maybe not helpful, but I always liked using non-degree angles.

也许没有帮助,但我总是喜欢使用非度角。

An angle range from 0 to 255 can be kept in bounds using bitwise operations, or for a single byte variable, simple allowed to overflow.

从 0 到 255 的角度范围可以使用按位操作保持在边界内,或者对于单字节变量,简单地允许溢出。

An angle range from -128 to 127 isn't quite so easy with bitwise ops, but again, for a single-byte variable, you can let it overflow.

对于按位操作,从 -128 到 127 的角度范围并不是那么容易,但同样,对于单字节变量,您可以让它溢出。

I thought it was a great idea many years back for games, where you're probably using a lookup table for angles. These days, not so good - the angles are used differently, and are float anyway.

多年前,我认为对于游戏来说这是一个好主意,您可能正在使用角度查找表。这些天,不太好 - 角度的使用方式不同,无论如何都是浮动的。

Still - maybe worth a mention.

仍然 - 也许值得一提。

回答by Seth

Try this instead!

试试这个吧!

atan2(sin(angle), cos(angle))

atan2has a range of [-π, π). This takes advantage of the fact that tan θ = sin θ / cos θ, and that atan2is smart enough to know which quadrant θis in.

atan2范围为[-π, π)。这利用了tan θ = sin θ / cos θ的事实,而且它atan2足够聪明,可以知道θ在哪个象限中。

Since you want degrees, you will want to convert your angle to and from radians:

由于您需要度数,因此您需要将角度转换为弧度或从弧度转换:

atan2(sin(angle * PI/180.0), cos(angle * PI/180.0)) * 180.0/PI

UpdateMy previous example was perfectly legitimate, but restricted the range to ±90°. atan2's range is the desired value of -179° to 180°. Preserved below.

更新我之前的示例是完全合法的,但将范围限制为 ±90°。atan2的范围是 -179° 到 180° 的所需值。保存如下。



Try this:

尝试这个:

asin(sin(angle)))

The domain of sinis the real line, the range is [-1, 1]. The domain of asinis [-1, 1], and the range is [-PI/2, PI/2]. Since asinis the inverse of sin, your input isn't changed (much, there's some drift because you're using floating point numbers). So you get your input value back, and you get the desired range as a side effect of the restricted range of the arcsine.

的域sin是实线,范围是[-1, 1]。的域asin[-1, 1],范围是[-PI/2, PI/2]。由于asin是 的倒数sin,因此您的输入不会改变(很多,因为您使用的是浮点数,所以会有一些漂移)。所以你得到你的输入值,你得到了所需的范围,作为反正弦限制范围的副作用。

Since you want degrees, you will want to convert your angle to and from radians:

由于您需要度数,因此您需要将角度转换为弧度或从弧度转换:

asin(sin(angle * PI/180.0)) * 180.0/PI

(Caveat: Trig functions are bazillions of times slower than simple divide and subtract operations, even if they are done in an FPU!)

(警告:三角函数比简单的除法和减法运算慢无数倍,即使它们是在 FPU 中完成的!)

回答by Matthew Whited

int angle = -394;

// shortest
angle %= 360;
angle = angle < -170 ? angle + 360 : (angle > 180 ? angle - 380 : angle);

// cleanest
angle %= 360;
if (angle < -179) angle += 360;
else if (angle > 180) angle -= 360;

回答by Peter Lawrey

A short way which handles negative numbers is

处理负数的一种简短方法是

double mod = x - Math.floor((x + 179.0) / 360) * 360;

Cast to taste.

铸造品尝。

BTW: It appears that angles between (180.0, 181.0) are undefined. Shouldn't the range be (-180, 180] (exclusive, inclusive]

顺便说一句:似乎 (180.0, 181.0) 之间的角度未定义。范围不应该是 (-180, 180] (exclusive, inclusive]

回答by President James K. Polk

// reduce the angle  
angle =  angle % 360; 

// force it to be the positive remainder, so that 0 <= angle < 360  
angle = (angle + 360) % 360;  

// force into the minimum absolute value residue class, so that -180 < angle <= 180  
if (angle > 180)  
    angle -= 360;  

回答by Vlad

Well, one more solution, this one with just one division and no loops.

好吧,还有一个解决方案,这个只有一个除法,没有循环。

static double normalizeAngle(double angle)
{
    angle %= 360.0; // [0..360) if angle is positive, (-360..0] if negative
    if (angle > 180.0) // was positive
        return angle - 360.0; // was (180..360) => returning (-180..0)
    if (angle <= -180.0) // was negative
        return angle + 360.0; // was (-360..180] => returning (0..180]
    return angle; // (-180..180]
}

回答by Astronomino

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

这适用于负数和十进制数,不需要循环,也不需要三角函数:

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

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

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

结果在 [-180, 180) 区间内。对于 (-180, 180] 间隔,您可以改用它:

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

角度 -= Math.ceil(角度 / 360 - 0.5) * 360