Jaka jest różnica między atan i atan2 w C ++?

157

Jaka jest różnica między ataniw atan2C ++?

yesraaj
źródło

Odpowiedzi:

131

std::atan2pozwala obliczyć arcus tangens wszystkich czterech kwadrantów. std::atanpozwala tylko na obliczanie z kwadrantów 1 i 4.

Chris Jester-Young
źródło
322

Z matematyki szkolnej wiemy, że styczna ma definicję

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

i rozróżniamy cztery ćwiartki na podstawie kąta, który zapewniamy funkcjom. Znakiem sin, cosi tanmieć następującą zależność (gdzie zaniedbujemy dokładnej wielokrotności π/2):

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

Biorąc pod uwagę, że wartość tan(α)jest dodatnia, nie możemy rozróżnić, czy kąt był z pierwszej, czy trzeciej ćwiartki, a jeśli jest ujemny, może pochodzić z drugiej lub czwartej ćwiartki. Tak więc zgodnie z konwencją atan()zwraca kąt z pierwszej lub czwartej ćwiartki (tj. -π/2 <= atan() <= π/2), Niezależnie od pierwotnego wejścia do stycznej.

Aby uzyskać pełną informację, nie możemy korzystać z wyniku dzielenia, sin(α) / cos(α)ale musimy osobno przyjrzeć się wartościom sinusa i cosinusa. I to właśnie atan2()robi. Zajmuje oba, sin(α)i cos(α)i rozwiązuje wszystkie cztery ćwiartki, dodając πdo wyniku atan()zawsze, gdy cosinus jest ujemny.

Uwaga:atan2(y, x) funkcja faktycznie odbywa się yi A xargumentu, który jest rzutem wektor o długości vi kąta αna Y- i osi x, tj

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

co daje związek

y/x = tan(α)

Wniosek: atan(y/x) wstrzymuje się pewne informacje i można tylko założyć, że dane wejściowe pochodziły z ćwiartki I lub IV. Natomiast atan2(y,x)pobiera wszystkie dane, a tym samym może rozwiązać prawidłowy kąt.

Mehrwolf
źródło
3
Jeden mały szczegół, w -π/2 <= atan() <= π/2rzeczywistości zakres obejmuje jeden punkt ( pi/2) z kwadrantu II.
Bozon Z
28

Inną rzeczą, o której należy wspomnieć, jest to, że atan2jest bardziej stabilny podczas obliczania stycznych przy użyciu wyrażenia takiego jak atan(y / x)i xwynosi 0 lub jest bliski 0.

Laserallan
źródło
Ciekawe, czy masz na to źródło? Czy to prawda w ogóle, czy tylko w przypadku C ++?
Gerard
26

Rzeczywiste wartości są podane w radianach, ale aby zinterpretować je w stopniach, będzie to:

  • atan = daje wartość kąta między -90 a 90
  • atan2 = daje wartość kąta między -180 a 180

W mojej pracy, która polega na obliczaniu różnych kątów, takich jak kurs i namiar w nawigacji, atan2w większości przypadków spełnia to zadanie.

Keugyeol
źródło
12

atan (x) Zwraca główną wartość stycznej łuku dla x, wyrażoną w radianach.

atan2 (y, x) Zwraca główną wartość stycznej łuku dla y / x, wyrażoną w radianach.

Zauważ, że z powodu niejednoznaczności znaku funkcja nie może z całą pewnością określić, w którym kwadrancie kąt mieści się tylko o wartość styczną (tylko atan). Możesz użyć atan2, jeśli potrzebujesz określić kwadrant.

RomanM
źródło
3
atan2 (x, y) -> atan2 (y, x)
yesraaj
Zakres wartości głównych to, (-pi,pi]ale atan2 ma zakres, [-pi,pi]więc zawiera jedną dodatkową wartość -piz innej gałęzi z powodu atan2(-0.0,x)for x<0.
Bozon Z
4

Wydaje mi się, że główne pytanie próbuje się dowiedzieć: „kiedy powinienem użyć jednego lub drugiego”, „którego powinienem użyć” lub „Czy używam właściwego”?

Wydaje mi się, że ważnym punktem jest to, że atan tylko miał dostarczać dodatnie wartości na krzywej w kierunku od prawej do góry, tak jak w przypadku wektorów czas-odległość. Cero jest zawsze w lewym dolnym rogu, a uda mogą poruszać się tylko w górę iw prawo, po prostu wolniej lub szybciej. atan nie zwraca liczb ujemnych, więc nie możesz śledzić rzeczy w 4 kierunkach na ekranie, po prostu dodając / odejmując wynik.

atan2 jest przeznaczone do tego, aby początek znajdował się pośrodku, a rzeczy mogą się cofać lub spadać. Tego właśnie użyłbyś w przedstawieniu na ekranie, ponieważ MA znaczenie, w jakim kierunku chcesz poprowadzić krzywą. Więc atan2 może dać ci liczby ujemne, ponieważ jego cero znajduje się w środku, a jego wynik jest czymś, co możesz wykorzystać do śledzenia rzeczy w 4 kierunkach.

sergio
źródło
2

Za pomocą atan2 możesz określić kwadrant, jak podano tutaj .

Możesz użyć atan2, jeśli potrzebujesz określić kwadrant.

Burkhard
źródło
2

Rozważmy trójkąt prostokątny. Oznaczamy przeciwprostokątną r, poziomą stronę y i pionową stronę x. Kąt zainteresowania α to kąt między x i r.

C ++ atan2(y, x)da nam wartość kąta α w radianach. atanjest używany, jeśli tylko znamy lub interesuje nas y / x, a nie y i x indywidualnie. Więc jeśli p = y / x, to aby otrzymać α, użylibyśmy atan(p).

Nie możesz użyć atan2do określenia kwadrantu, możesz użyć atan2tylko wtedy, gdy już wiesz, w którym kwadrancie się znajdujesz! W szczególności dodatnie x i y implikują pierwszą ćwiartkę, dodatnią y i ujemną x, drugą i tak dalej. atanlub atan2same zwracają liczbę dodatnią lub ujemną, nic więcej.

bheks
źródło
4
Jeśli wszystko, co masz p=y/x, nadal możesz używać atan2(p,1).
Mark Ransom
0

Poniższy Mehrwolf jest poprawny, ale oto heurystyka, która może pomóc:

Jeśli pracujesz w dwuwymiarowym układzie współrzędnych, co często ma miejsce przy programowaniu odwrotnej stycznej, zdecydowanie powinieneś użyć atan2. Da pełny zakres kątów 2 pi i zajmie się zerami we współrzędnej x za Ciebie.

Inaczej mówiąc, atan (y / x) jest praktycznie zawsze błędne. Atan należy używać tylko wtedy, gdy argument nie może być traktowany jako y / x.

Nick Mulgan
źródło
0

atan2(y,x)jest zwykle używany do konwersji współrzędnych kartezjańskich na współrzędne biegunowe. Poda kąt, podczas gdy sqrt(x*x+y*y)lub, jeśli jest dostępny, hypot(y,x)poda rozmiar.

atan(x)jest po prostu odwrotnością opalenizny. W irytującym przypadku, którego musisz użyć, atan(y/x)ponieważ twój system nie zapewnia atan2, musiałbyś wykonać dodatkowe kontrole pod kątem znaków xi yi dla x=0, aby uzyskać prawidłowy kąt.

Uwaga: atan2(y,x) jest zdefiniowany dla wszystkich rzeczywistych wartości yi x, z wyjątkiem przypadku, gdy oba argumenty mają wartość zero.

user3303328
źródło
0

W atan2, wyjście jest: -pi< atan2(y,x)< pi
i atan, wyjście jest: -pi/2< atan(y/x)< pi/2 // NIE dawki rozważyć kwartał.
Jeśli chcesz uzyskać orientację między 0a2*pi (jak matematyka w szkole średniej), musimy użyć atan2, a dla wartości ujemnych dodaj znak, 2*piaby uzyskać końcowy wynik między 0a 2*pi.
Oto kod źródłowy Java, aby to jasno wyjaśnić:

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
źródło