¿Cuál es la diferencia entre atan y atan2 en C ++?


157

¿Cuál es la diferencia entre atany atan2en C ++?

Respuestas:



322

Por matemática escolar sabemos que la tangente tiene la definición

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

y diferenciamos entre cuatro cuadrantes en función del ángulo que proporcionamos a las funciones. El signo de sin, cosy tantiene la siguiente relación (donde descuidamos los múltiplos exactos de π/2):

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

Dado que el valor de tan(α)es positivo, no podemos distinguir si el ángulo era del primer o tercer cuadrante y si es negativo, podría provenir del segundo o cuarto cuadrante. Entonces, por convención, atan()devuelve un ángulo desde el primer o cuarto cuadrante (es decir -π/2 <= atan() <= π/2), independientemente de la entrada original a la tangente.

Para recuperar la información completa, no debemos usar el resultado de la división, sin(α) / cos(α)sino que tenemos que mirar los valores del seno y el coseno por separado. Y esto es lo que atan2()hace. Toma ambos, el sin(α)y cos(α)y resuelve los cuatro cuadrantes agregando πal resultado de atan()cuando el coseno es negativo.

Observación: la atan2(y, x)función en realidad toma un yy un xargumento, que es la proyección de un vector con longitud vy ángulo αen los ejes yy x, es decir

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

lo que da la relación

y/x = tan(α)

Conclusión: atan(y/x) se retiene cierta información y solo se puede suponer que la entrada provino de los cuadrantes I o IV. Por el contrario, atan2(y,x)obtiene todos los datos y, por lo tanto, puede resolver el ángulo correcto.


3
Un pequeño detalle, el rango en -π/2 <= atan() <= π/2realidad incluye un punto ( pi/2) del cuadrante II.
Z boson

28

Otra cosa a mencionar es que atan2es más estable cuando se calculan tangentes usando una expresión como atan(y / x)y xes 0 o cercano a 0.


Interesante, ¿tienes una fuente para esto? ¿Es esto cierto en general o solo para C ++?
Gerard

26

Los valores reales están en radianes, pero para interpretarlos en grados será:

  • atan = da un valor de ángulo entre -90 y 90
  • atan2 = da un valor de ángulo entre -180 y 180

Para mi trabajo, que implica el cálculo de varios ángulos, como rumbo y rumbo en la navegación, atan2en la mayoría de los casos hace el trabajo.


12

atan (x) Devuelve el valor principal del arco tangente de x, expresado en radianes.

atan2 (y, x) Devuelve el valor principal del arco tangente de y / x, expresado en radianes.

Tenga en cuenta que debido a la ambigüedad del signo, una función no puede determinar con certeza en qué cuadrante el ángulo cae solo por su valor tangente (solo atan). Puede usar atan2 si necesita determinar el cuadrante.


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

El rango de valores principales es (-pi,pi]pero atan2 tiene el rango, [-pi,pi]por lo que incluye un valor adicional -pide otra rama debido a atan2(-0.0,x)for x<0.
Z boson

4

Supongo que la pregunta principal trata de averiguar: "¿cuándo debo usar uno u otro", o "qué debo usar", o "¿Estoy usando el correcto"?

Supongo que el punto importante es que atan solo estaba destinado a alimentar valores positivos en una curva de dirección derecha hacia arriba, como para los vectores de tiempo-distancia. Cero siempre está en la parte inferior izquierda, y los thigs solo pueden subir y bajar, solo más lento o más rápido. atan no devuelve números negativos, por lo que no puede rastrear cosas en las 4 direcciones en una pantalla simplemente sumando / restando su resultado.

atan2 está destinado a que el origen esté en el medio, y las cosas pueden ir hacia atrás o hacia abajo. Eso es lo que usarías en una representación de pantalla, porque NO importa en qué dirección quieres que vaya la curva. Entonces atan2 puede darte números negativos, porque su cero está en el centro, y su resultado es algo que puedes usar para rastrear cosas en 4 direcciones.


2

Con atan2 puede determinar el cuadrante como se indica aquí .

Puede usar atan2 si necesita determinar el cuadrante.


2

Considere un triángulo rectángulo en ángulo. Rotulamos la hipotenusa r, el lado horizontal y y el lado vertical x. El ángulo de interés α es el ángulo entre x y r.

C ++ atan2(y, x)nos dará el valor del ángulo α en radianes. atanse usa si solo conocemos o estamos interesados ​​en y / x no en y y x individualmente. Entonces, si p = y / x entonces para obtener α lo usaríamos atan(p).

No puede usar atan2para determinar el cuadrante, ¡puede usar atan2solo si ya sabe en qué cuadrante está! En particular, positivo x e y implican el primer cuadrante, positivo y negativo x, el segundo y así sucesivamente. atano atan2ellos mismos simplemente devuelven un número positivo o negativo, nada más.


44
Si todo lo que tiene es p=y/xque todavía puede usar atan2(p,1).
Mark Ransom

0

Mehrwolf a continuación es correcto, pero aquí hay una heurística que puede ayudar:

Si está trabajando en un sistema de coordenadas bidimensional, que suele ser el caso para programar la tangente inversa, definitivamente debe usar atan2. Le dará el rango completo de ángulos de 2 pi y se encargará de los ceros en la coordenada x por usted.

Otra forma de decir esto es que atan (y / x) está prácticamente siempre equivocado. Solo use atan si el argumento no puede considerarse como y / x.


0

atan2(y,x)generalmente se usa si desea convertir coordenadas cartesianas en coordenadas polares. Le dará el ángulo, mientras que sqrt(x*x+y*y)o, si está disponible, hypot(y,x)le dará el tamaño.

atan(x)es simplemente el inverso del bronceado. En el caso molesto que tiene que usar atan(y/x)porque su sistema no proporciona atan2, tendría que hacer verificaciones adicionales de los signos xy y, y para x=0, para obtener el ángulo correcto.

Nota: atan2(y,x) se define para todos los valores reales de yy x, excepto para el caso en que ambos argumentos son cero.


0

En atan2, la salida es: -pi< atan2(y,x)< pi
y atan, la salida es: -pi/2< atan(y/x)< pi/2 // no aumenta en cuenta el trimestre.
Si desea obtener la orientación entre 0y 2*pi(como las matemáticas de la escuela secundaria), necesitamos usar atan2 y para valores negativos agregue el 2*pipara obtener el resultado final entre 0y 2*pi.
Aquí está el código fuente de Java para explicarlo claramente:

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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.