Qual é a diferença entre atan e atan2 em C ++?


157

Qual é a diferença entre atane atan2em C ++?

Respostas:



322

Da matemática escolar sabemos que a tangente tem a definição

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

e diferenciamos entre quatro quadrantes com base no ângulo que fornecemos às funções. O sinal de sin, cose tantem o seguinte relacionamento (onde negligenciamos os múltiplos exatos de π/2):

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

Dado que o valor de tan(α)é positivo, não podemos distinguir se o ângulo era do primeiro ou terceiro quadrante e se é negativo, poderia vir do segundo ou quarto quadrante. Assim, por convenção, atan()retorna um ângulo do primeiro ou quarto quadrante (ou seja -π/2 <= atan() <= π/2), independentemente da entrada original para a tangente.

Para recuperar todas as informações, não devemos usar o resultado da divisão, sin(α) / cos(α)mas precisamos examinar os valores do seno e do cosseno separadamente. E é isso que atan2()faz. Demora tanto, a sin(α)e cos(α)e resolve todos os quatro quadrantes, adicionando πao resultado de atan()sempre que o co-seno é negativo.

Observação: A atan2(y, x)função realmente leva a ye um xargumento, que é a projeção de um vetor com comprimento ve ângulo αnos eixos y e x, ou seja,

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

o que dá a relação

y/x = tan(α)

Conclusão: atan(y/x) retém algumas informações e só pode assumir que a entrada veio dos quadrantes I ou IV. Por outro lado, atan2(y,x)obtém todos os dados e, portanto, pode resolver o ângulo correto.


3
Um pequeno detalhe, o intervalo -π/2 <= atan() <= π/2inclui , na verdade, um ponto ( pi/2) do quadrante II.
Z boson

28

Outra coisa a mencionar é que atan2é mais estável ao calcular tangentes usando uma expressão como atan(y / x)e xé 0 ou próximo de 0.


Interessante, você tem uma fonte para isso? Isso é verdade em geral ou apenas para C ++?
Gerard

26

Os valores reais estão em radianos, mas para interpretá-los em graus, será:

  • atan = fornece um valor de ângulo entre -90 e 90
  • atan2 = fornece um valor de ângulo entre -180 e 180

Para o meu trabalho que envolve o cálculo de vários ângulos, como rumo e rumo na navegação, atan2na maioria dos casos faz o trabalho.


12

atan (x) Retorna o valor principal do arco tangente de x, expresso em radianos.

atan2 (y, x) Retorna o valor principal do arco tangente de y / x, expresso em radianos.

Observe que, devido à ambiguidade do sinal, uma função não pode determinar com certeza em que quadrante o ângulo cai apenas pelo seu valor tangente (somente atan). Você pode usar atan2 se precisar determinar o quadrante.


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

O intervalo dos valores de princípio é (-pi,pi]mas atan2 possui o intervalo, [-pi,pi]portanto inclui um valor extra -pide outro ramo devido a atan2(-0.0,x)for x<0.
Z boson

4

Eu acho que a pergunta principal tenta descobrir: "quando devo usar um ou outro", ou "qual devo usar" ou "Estou usando o correto"?

Acho que o ponto importante é que apenas um objetivo era alimentar valores positivos em uma curva de direção para cima, como para vetores de distância no tempo. O Cero está sempre no canto inferior esquerdo, e os espinhos só podem subir e direita, apenas mais devagar ou mais rápido. atan não retorna números negativos; portanto, você não pode rastrear coisas nas quatro direções da tela apenas adicionando / subtraindo o resultado.

atan2 é destinado à origem no meio, e as coisas podem ir para trás ou para baixo. Isso é o que você usaria em uma representação de tela, porque importa em que direção você deseja que a curva siga. Portanto, o atan2 pode fornecer números negativos, porque o cero está no centro e o resultado é algo que você pode usar para rastrear as coisas em 4 direções.


2

Com atan2, você pode determinar o quadrante conforme indicado aqui .

Você pode usar atan2 se precisar determinar o quadrante.


2

Considere um triângulo retângulo. Nós rotulamos a hipotenusa r, o lado horizontal y e o lado vertical x. O ângulo de interesse α é o ângulo entre x e r.

C ++ atan2(y, x)nos dará o valor do ângulo α em radianos. atané usado se apenas conhecermos ou estivermos interessados ​​em y / x não yex individualmente. Portanto, se p = y / x, para obter α, usaríamos atan(p).

Você não pode usar atan2para determinar o quadrante, só pode usar atan2se já souber em qual quadrante está! Em particular, xey positivo implica o primeiro quadrante, y positivo e x negativo, o segundo e assim por diante. atanou atan2eles mesmos simplesmente retornam um número positivo ou negativo, nada mais.


4
Se tudo que você tem é p=y/xvocê ainda pode usar atan2(p,1).
Mark Ransom

0

Mehrwolf abaixo está correto, mas aqui está uma heurística que pode ajudar:

Se você estiver trabalhando em um sistema de coordenadas bidimensional, que geralmente é o caso para programar a tangente inversa, use definitivamente atan2. Ele fornecerá todo o intervalo de 2 pi e cuidará dos zeros na coordenada x para você.

Outra maneira de dizer isso é que atan (y / x) está quase sempre errado. Use atan apenas se o argumento não puder ser pensado como y / x.


0

atan2(y,x)é geralmente usado se você deseja converter coordenadas cartesianas em coordenadas polares. Ele fornecerá o ângulo, enquanto sqrt(x*x+y*y)ou, se disponível, hypot(y,x)o tamanho.

atan(x)é simplesmente o inverso do bronzeado. No caso irritante que você precisa usar atan(y/x)porque o sistema não fornece atan2, você teria que fazer verificações adicionais quanto aos sinais de xe ye para x=0obter o ângulo correto.

Nota: atan2(y,x) é definido para todos os valores reais de ye x, exceto no caso em que ambos os argumentos são zero.


0

Em atan2, a saída é: -pi< atan2(y,x)< pi
e atan, a saída é: -pi/2< atan(y/x)< pi/2 // Ela não se considerar o trimestre.
Se você deseja obter a orientação entre 0e 2*pi(como a matemática do ensino médio), precisamos usar o atan2 e, para valores negativos, adicionar o 2*pipara obter o resultado final entre 0e 2*pi.
Aqui está o código-fonte Java para explicá-lo 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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.