【问题标题】:What is the difference between atan and atan2 in C++?C ++中的atan和atan2有什么区别?
【发布时间】:2010-09-21 22:56:18
【问题描述】:

C++ 中atanatan2 有什么区别?

【问题讨论】:

    标签: c++ math.h


    【解决方案1】:

    std::atan2 允许计算所有四个象限的反正切。 std::atan 只允许从象限 1 和 4 计算。

    【讨论】:

      【解决方案2】:

      使用 atan2,您可以确定here 所述的象限。

      如果需要,可以使用 atan2 确定象限。

      【讨论】:

        【解决方案3】:

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

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

        请注意,由于符号不明确,函数不能仅通过其正切值(仅 atan)确定角度落在哪个象限。如果需要确定象限,可以使用atan2。

        【讨论】:

        • 原则值的范围是(-pi,pi],但atan2 的范围是[-pi,pi],因此它包括来自另一个分支的一个额外值-pi,因为atan2(-0.0,x) 用于x<0
        【解决方案4】:

        另外要提到的是,atan2 在使用像 atan(y / x)x 为 0 或接近 0 的表达式计算切线时更稳定。

        【讨论】:

        • 有趣,你有这个的来源吗?这是普遍情况还是仅适用于 C++?
        【解决方案5】:

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

        C++ atan2(y, x) 将为我们提供角度 α 的弧度值。 atan 仅在我们只知道或对 y/x 而不是 y 和 x 感兴趣时使用。所以如果 p = y/x 然后要获得 α,我们将使用 atan(p)

        您不能使用atan2 来确定象限,只有当您已经知道您在哪个象限时才能使用atan2!特别是正 x 和 y 意味着第一象限,正 y 和负 x,第二象限,依此类推。 atanatan2 本身只是返回一个正数或负数,仅此而已。

        【讨论】:

        • 如果你只有p=y/x,你仍然可以使用atan2(p,1)
        • @MarkRansom 当然可以,但它会慢一点,并且返回的信息不会比atan 多,对吧?
        • @BillKotsias 不确定为什么它会变慢,但你说得对,它不会像 atan 那样包含象限。
        【解决方案6】:

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

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

        我们根据我们提供给函数的角度来区分四个象限。 sincostan 的符号有以下关系(这里我们忽略了π/2 的确切倍数):

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

        鉴于tan(α)的值为正,我们无法区分角度是来自第一象限还是第三象限,如果为负,则可能来自第二象限或第四象限。所以按照惯例,atan() 从第一或第四象限返回一个角度(即-π/2 &lt;= atan() &lt;= π/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) 获取所有数据,因此可以解析正确的角度。

        【讨论】:

        • 一个小细节,-π/2 &lt;= atan() &lt;= π/2 的范围实际上包括第二象限的一个点 (pi/2)。
        • 太棒了,谢谢
        【解决方案7】:

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

        我想重要的一点是 atan 仅用于在向右向上的方向曲线中提供正值,例如时间距离向量。零总是在左下角,而thigs只能上下左右,只是更慢或更快。 atan 不返回负数,因此您无法仅通过添加/减去结果来跟踪屏幕上 4 个方向的内容。

        atan2 旨在让原点位于中间,并且事情可以向后或向下。这就是您在屏幕表示中使用的内容,因为您希望曲线走向哪个方向并不重要。所以 atan2 可以给你负数,因为它的零在中心,它的结果是你可以用来追踪 4 个方向的东西。

        【讨论】:

          【解决方案8】:

          实际值以弧度为单位,但以度为单位表示:

          • atan = 给出 -90 到 90 之间的角度值
          • atan2 = 给出 -180 到 180 之间的角度值

          对于我在导航中涉及计算各种角度(例如航向和方位)的工作,atan2 在大多数情况下都可以完成这项工作。

          【讨论】:

            【解决方案9】:

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

            如果您在二维坐标系中工作,这通常是编程反正切的情况,您绝对应该使用 atan2。它将提供完整的 2 pi 角度范围,并为您处理 x 坐标中的零。

            另一种说法是 atan(y/x) 实际上总是错误的。仅当参数不能被认为是 y/x 时​​才使用 atan。

            【讨论】:

              【解决方案10】:

              atan2(y,x)通常用于将笛卡尔坐标转换为极坐标。它会为您提供角度,而sqrt(x*x+y*y)hypot(y,x) 会为您提供尺寸。

              atan(x) 只是 tan 的倒数。在烦人的情况下,您必须使用atan(y/x),因为您的系统不提供atan2,您必须对xyx=0 的符号进行额外检查,以便获得正确的角度。

              注意:atan2(y,x) 是为 yx 的所有实数值定义的,除非两个参数都为零。

              【讨论】:

                【解决方案11】:

                在atan2中,输出为:-pi atan2(y,x) pi
                在 atan 中,输出为:-pi/2 atan(y/x) pi/2 //它不考虑季度。
                如果您想获得02*pi 之间的方向(如高中数学),我们需要使用atan2,对于负值添加2*pi 以获得0 和@ 之间的最终结果987654331@.
                这是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
                

                【讨论】:

                  猜你喜欢
                  • 2014-11-05
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2014-11-29
                  • 1970-01-01
                  • 2014-03-01
                  • 2011-04-05
                  • 2011-10-18
                  相关资源
                  最近更新 更多