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

157

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

yesraaj
fonte

Respostas:

131

std::atan2permite calcular o arco tangente de todos os quatro quadrantes. std::atansó permite calcular a partir dos quadrantes 1 e 4.

Chris Jester-Young
fonte
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.

Mehrwolf
fonte
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.

Laserallan
fonte
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.

Keugyeol
fonte
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.

RomanM
fonte
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.

sergio
fonte
2

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

Você pode usar atan2 se precisar determinar o quadrante.

Burkhard
fonte
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.

bheks
fonte
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.

Nick Mulgan
fonte
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.

user3303328
fonte
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
user497884
fonte