有没有一种简单的方法将角度(以度为单位)转换为介于-179和180之间?我确定可以使用mod(%)和一些if语句,但这变得很丑陋:
//Make angle between 0 and 360
angle%=360;
//Make angle between -179 and 180
if (angle>180) angle-=360;
似乎应该有一个简单的数学运算可以同时执行这两个语句。暂时可能需要为转换创建一个静态方法。
有没有一种简单的方法将角度(以度为单位)转换为介于-179和180之间?我确定可以使用mod(%)和一些if语句,但这变得很丑陋:
//Make angle between 0 and 360
angle%=360;
//Make angle between -179 and 180
if (angle>180) angle-=360;
似乎应该有一个简单的数学运算可以同时执行这两个语句。暂时可能需要为转换创建一个静态方法。
// 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;
%
运算符是余数而不是模数,因此在像Python这样的语言中,第二行angle = (angle + 360) % 360
并不需要使其适用于负数(尽管它不会有任何损害)。详情请见:https://dev59.com/f2435IYBdhLWcg3wfQJ9。 - Steve试试这个替代方案!
atan2(sin(angle), cos(angle))
atan2
的范围是[-π, π)。这利用了tan θ = sin θ / cos θ的事实,并且atan2
足够聪明,知道θ处于哪个象限。
由于你想要度数,所以需要将角度从弧度转换并转回去:
atan2(sin(angle * PI/180.0), cos(angle * PI/180.0)) * 180.0/PI
更新
我的先前示例是完全合法的,但将范围限制在±90度内。 atan2
的范围是所需的-179度至180度。以下保留原文。
尝试这样做:
asin(sin(angle)))
sin
函数的定义域是实数轴,值域为[-1, 1]
。而asin
函数的定义域为[-1, 1]
,值域为[-PI/2, PI/2]
。由于asin
是sin
的反函数,所以输入值(因为使用浮点数可能会有一些漂移)不会改变太多,您将会得到原始的输入值,并通过限制范围来得到期望的输出值。
如果您需要使用角度,则需要将角度值转换为弧度值,然后再转换回去。
asin(sin(angle * PI/180.0)) * 180.0/PI
(注意:即使在FPU中执行三角函数,它们的速度也比简单的除法和减法操作慢数十亿倍!)
我知道岁月已经过去,但是仍然。
此解决方案不包含循环、减法或模运算(允许归一化为弧度间隔)。适用于任何输入,包括负值、大值和边缘情况。
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):
这适用于负数和小数,并且不需要循环或三角函数:
angle -= Math.floor(angle / 360 + 0.5) * 360
结果在[-180,180)区间内。对于(-180,180]区间,您可以使用以下方法:
angle -= Math.ceil(angle / 360 - 0.5) * 360
angle
必须是一个float
类型,否则整数运算将会启动。使用angle -= Math.ceil((double)angle / 360 - 0.5) * 360
或类似的方法可以获得最佳安全性。我喜欢这个答案,应该排名第一。 - Cory-G不是很聪明,但没有条件。
angle = (angle + 179) % 360 - 179;
但是我不确定Java如何处理负数的模运算。这只有在-1模360等于359时才有效。
更新
刚刚查看了文档,a % b
会产生一个值,在-(|b| - 1)
和+(|b| - 1)
之间,因此代码是有问题的。为了应对模运算符返回的负值,必须使用以下方法。
angle = ((angle + 179) % 360 + 360) % 360 - 179;
但是...不行...永远不行...使用与您最初的解决方案类似的东西,但对小于-179的值进行修正。
我知道我来晚了,但是...
大多数答案都不好,因为它们试图聪明而简洁,然后没有考虑到边缘情况。
这个方法稍微冗长一些,但如果你想让它工作,只需加入使其工作的逻辑。不要试图聪明。
int normalizeAngle(int angle) { int newAngle = angle; while (newAngle <= -180) newAngle += 360; while (newAngle > 180) newAngle -= 360; return newAngle; }
这个方法可行且相对简单,没有试图过于花哨。请注意,只有零或一个while循环会运行。
double mod = x - Math.floor((x + 179.0) / 360) * 360;
品尝铸造。
顺便说一句:似乎角度在(180.0,181.0)之间是未定义的。范围不应该是(-180,180](排除,包含)吗?
以下是仅限整数的解决方案:
int normalize(int angle)
{
angle %= 360;
int fix = angle / 180; // Integer division!!
return (fix) ? angle - (360 * (fix)) : angle;
}
我已经制定了一个用于圆形值方向的公式
以保持角度在0到359之间的方法是:
angle + Math.ceil( -angle / 360 ) * 360
angle + Math.ceil( (-angle-179) / 360 ) * 360
这将使其方向偏移约-179,保持实际角度不变。
转移角度方向的通用公式可以是:
angle + Math.ceil( (-angle+shift) / 360 ) * 360