C ++中的atan和atan2有什么区别?


157

atanatan2C ++ 和有什么不一样?

Answers:



322

从学校数学中我们知道切线的定义

tan(α) = sin(α) / cos(α)

然后根据提供给函数的角度区分四个象限。的符号sincos并且tan具有以下关系(我们忽略的精确倍数π/2):

  Quadrant    Angle              sin   cos   tan
-------------------------------------------------
  I           0    < α < π/2      +     +     +
  II          π/2  < α < π        +     -     -
  III         π    < α < 3π/2     -     -     +
  IV          3π/2 < α < 2π       -     +     -

鉴于的值为tan(α)正,我们无法区分该角度是来自第一象限还是第三象限,如果该角度为负,则可能来自第二象限或第四象限。因此,按照惯例,无论切线的原始输入如何,都atan()从第一或第四象限(即-π/2 <= atan() <= π/2)返回一个角度。

为了获取全部信息,我们不能使用除法的结果,sin(α) / cos(α)而必须分别查看正弦和余弦的值。这是什么atan2()呢。这需要两者的sin(α)cos(α),并通过添加解决所有四个象限π到的结果,atan()每当余弦为负。

备注:atan2(y, x)函数实际上需要一个y和一个x参数,它是与长度的矢量的投影v和角度α上的y轴和x轴,即

y = v * sin(α)
x = v * cos(α)

给出关系

y/x = tan(α)

结论: atan(y/x)保留了一些信息,只能假定输入来自象限I或IV。相反,atan2(y,x)获取所有数据并因此可以解析正确的角度。


3
一个小细节,范围-π/2 <= atan() <= π/2实际上包括pi/2象限II中的一个点()。
Z玻色子2015年

28

还要提到的另一件事是,atan2当使用诸如atan(y / x)和的表达式来计算切线并且x为0或接近0 时,它更加稳定。


有趣的是,您有此资源吗?这是一般情况还是仅适用于C ++?
杰拉德2014年

26

实际值以弧度为单位,但以度为单位来解释,则为:

  • atan =给出-90至90之间的角度值
  • atan2 =给出介于-180和180之间的角度值

对于我的工作而言,它涉及导航中的航向和方位等各种角度的计算,atan2在大多数情况下都可以完成工作。


12

atan(x)返回x的反正切的主值,以弧度表示。

atan2(y,x)返回y / x的反正切的主值,以弧度表示。

注意,由于符号模糊,函数不能确定确定象限中的角度仅按其切线值落下(仅atan)。如果需要确定象限,则可以使用atan2。


3
atan2(x,y)-> atan2(y,x)
yesraaj

原则值的范围为,(-pi,pi]但atan2具有范围,[-pi,pi]因此-pi由于atan2(-0.0,x)for ,它包含来自另一个分支的一个额外值x<0
Z玻色子2015年

4

我猜主要问题试图弄清楚:“我什么时候应该使用一个或另一个”,或者“我应该使用哪个”,或者“我使用正确的一个”?

我想最重要的一点是atan仅用于向右向上的方向曲线提供正值,例如用于时距矢量。Cero始终位于左下角,而thig只能向上或向右移动,或者变慢或变快。atan不会返回负数,因此仅通过添加/减去其结果就无法在屏幕上的4个方向上追踪事物。

atan2旨在使原点位于中间,并且事物可以向后或向下移动。那就是您要在屏幕表示中使用的内容,因为它与曲线的走向无关紧要。所以atan2可以给您负数,因为它的Cero位于中心,并且它的结果是可以用来在4个方向上跟踪事物的东西。



2

考虑一个直角三角形。我们标记斜边r,水平边y和垂直边x。感兴趣角α是x和r之间的角。

C ++ atan2(y, x)将为我们提供以弧度为单位的角度α值。 atan如果我们仅了解y / x或对y / x感兴趣,而不是分别对y和x感兴趣,则使用。因此,如果p = y / x,则使用α即可atan(p)

您不能使用atan2确定象限,atan2只有在您知道自己所在的象限时才可以使用!特别是,正x和y表示第一个象限,正y和负x表示第二象限,依此类推。atanatan2自己只是返回一个正数或负数,仅此而已。


4
如果您所拥有的只是p=y/x您仍然可以使用atan2(p,1)
Mark Ransom'3

0

下面的Mehrwolf是正确的,但这是一种启发式方法,可能会有所帮助:

如果在二维坐标系中工作(通常是对反切线进行编程的情况),则应绝对使用atan2。它将提供完整的2 pi角度范围,并为您照顾x坐标中的零。

换句话说,atan(y / x)实际上总是错误的。仅当无法将参数视为y / x时才使用atan。


0

atan2(y,x)通常用于要将直角坐标转换为极坐标的情况。它将为您提供角度sqrt(x*x+y*y),如果可能的话,hypot(y,x)会给您提供尺寸。

atan(x)只是tan的倒数。在烦人的情况下,您必须使用atan(y/x)系统,因为您的系统没有提供atan2,所以您必须对xy,和的符号进行其他检查x=0才能获得正确的角度。

注: atan2(y,x)为所有真正的价值定义yx,除情况下,当两个参数是零。


0

在ATAN2,输出是:-pi< atan2(y,x)< pi
和ATAN,输出是:-pi/2< atan(y/x)< pi/2 //它计量不考虑四分之一。
如果您想获得介于0和之间的方向2*pi(例如高中数学),我们需要使用atan2,对于负值,请添加2*pi以获得介于0和之间的最终结果2*pi
以下是Java源代码,可以对其进行清晰说明:

System.out.println(Math.atan2(1,1)); //pi/4 in the 1st quarter
System.out.println(Math.atan2(1,-1)); //(pi/4)+(pi/2)=3*(pi/4) in the 2nd quarter

System.out.println(Math.atan2(-1,-1 ));//-3*(pi/4) and it is less than 0.
System.out.println(Math.atan2(-1,-1)+2*Math.PI); //5(pi/4) in the 3rd quarter

System.out.println(Math.atan2(-1,1 ));//-pi/4 and it is less than 0.
System.out.println(Math.atan2(-1,1)+2*Math.PI); //7*(pi/4) in the 4th quarter

System.out.println(Math.atan(1 ));//pi/4
System.out.println(Math.atan(-1 ));//-pi/4
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.