Respostas:
std::atan2
permite calcular o arco tangente de todos os quatro quadrantes. std::atan
só permite calcular a partir dos quadrantes 1 e 4.
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
, cos
e tan
tem 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 y
e um x
argumento, que é a projeção de um vetor com comprimento v
e â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.
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.
Os valores reais estão em radianos, mas para interpretá-los em graus, será:
atan
= fornece um valor de ângulo entre -90 e 90atan2
= fornece um valor de ângulo entre -180 e 180Para o meu trabalho que envolve o cálculo de vários ângulos, como rumo e rumo na navegação, atan2
na maioria dos casos faz o trabalho.
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.
(-pi,pi]
mas atan2 possui o intervalo, [-pi,pi]
portanto inclui um valor extra -pi
de outro ramo devido a atan2(-0.0,x)
for x<0
.
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.
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 atan2
para determinar o quadrante, só pode usar atan2
se 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. atan
ou atan2
eles mesmos simplesmente retornam um número positivo ou negativo, nada mais.
p=y/x
você ainda pode usar atan2(p,1)
.
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.
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 x
e y
e para x=0
obter o ângulo correto.
Nota: atan2(y,x)
é definido para todos os valores reais de y
e x
, exceto no caso em que ambos os argumentos são zero.
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 0
e 2*pi
(como a matemática do ensino médio), precisamos usar o atan2 e, para valores negativos, adicionar o 2*pi
para obter o resultado final entre 0
e 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
-π/2 <= atan() <= π/2
inclui , na verdade, um ponto (pi/2
) do quadrante II.