Ответы:
std::atan2
позволяет рассчитать арктангенс всех четырех квадрантов. std::atan
позволяет рассчитывать только по квадрантам 1 и 4.
Из школьной математики мы знаем, что касательная имеет определение
tan(α) = sin(α) / cos(α)
и мы различаем четыре квадранта в зависимости от угла зрения функций. Знак sin
, cos
и tan
имеют следующие отношения (где мы пренебрегаем точными коэффициентами π/2
):
Quadrant Angle sin cos tan
-------------------------------------------------
I 0 < α < π/2 + + +
II π/2 < α < π + - -
III π < α < 3π/2 - - +
IV 3π/2 < α < 2π - + -
Учитывая, что значение tan(α)
положительно, мы не можем различить, был ли угол от первого или третьего квадранта, и если он отрицателен, он может исходить из второго или четвертого квадранта. Таким образом, по соглашению, atan()
возвращает угол из первого или четвертого квадранта (то есть -π/2 <= atan() <= π/2
), независимо от исходного ввода в касательную.
Чтобы получить полную информацию, мы не должны использовать результат деления, sin(α) / cos(α)
но мы должны смотреть на значения синуса и косинуса отдельно. И это то, что atan2()
делает. Он принимает оба, sin(α)
и cos(α)
и разрешает все четыре квадранта, добавляя π
к результату atan()
всякий раз, когда косинус отрицателен.
Примечание:atan2(y, x)
функция фактически принимает y
и в x
аргумент, который является проекцией вектора с длиной v
и углом α
на y- и оси х, т.е.
y = v * sin(α)
x = v * cos(α)
который дает отношение
y/x = tan(α)
Вывод:
atan(y/x)
удерживается некоторая информация и можно только предполагать, что входные данные поступили из квадрантов I или IV. Напротив, atan2(y,x)
получает все данные и, следовательно, может разрешить правильный угол.
Еще одна вещь, которую стоит упомянуть, это то, что atan2
она более стабильна при вычислении касательных с использованием выражения, подобного atan(y / x)
и x
равного 0 или близкого к 0.
Фактические значения в радианах, но для их интерпретации в градусах это будет:
atan
= дает значение угла между -90 и 90atan2
= дает значение угла между -180 и 180Для моей работы, которая включает в себя вычисление различных углов, таких как направление и направление в навигации, atan2
в большинстве случаев делает эту работу.
atan (x) Возвращает главное значение арктангенса x, выраженное в радианах.
atan2 (y, x) Возвращает главное значение арктангенса y / x, выраженное в радианах.
Обратите внимание, что из-за неоднозначности знака функция не может с уверенностью определить, в каком квадранте угол падает только по его значению касательной (только atan). Вы можете использовать atan2, если вам нужно определить квадрант.
(-pi,pi]
но у atan2 есть диапазон, [-pi,pi]
поэтому он включает одно дополнительное значение -pi
из другой ветви из-за atan2(-0.0,x)
for x<0
.
Я предполагаю, что главный вопрос пытается выяснить: «когда я должен использовать тот или другой», или «который я должен использовать», или «я использую правильный»?
Я предполагаю, что важным моментом является то, что atan предназначен только для подачи положительных значений по кривой направления вправо-вверх, как для векторов времени-расстояния. Cero всегда находится внизу слева, и пальцы могут двигаться только вверх и вправо, только медленнее или быстрее. atan не возвращает отрицательные числа, поэтому вы не можете отследить вещи в четырех направлениях на экране, просто сложив / вычтя результат.
atan2 предназначен для того, чтобы источник находился посередине, и все может идти назад или вниз. Это то, что вы бы использовали в представлении на экране, потому что это НЕ имеет значения, в каком направлении вы хотите, чтобы кривая шла. Таким образом, atan2 может дать вам отрицательные числа, потому что его cero находится в центре, а его результат - то, что вы можете использовать для отслеживания вещей в 4 направлениях.
Рассмотрим прямоугольный треугольник. Мы помечаем гипотенузу r, горизонтальную сторону y и вертикальную сторону x. Угол интереса α - это угол между x и r.
C ++ atan2(y, x)
даст нам значение угла α в радианах.
atan
используется, если мы знаем или заинтересованы только в y / x, а не в y и x по отдельности. Поэтому, если p = y / x, то для получения α мы будем использовать atan(p)
.
Вы не можете использовать atan2
для определения квадранта, вы можете использовать, atan2
только если вы уже знаете, какой квадрант ваш в! В частности, положительные x и y означают первый квадрант, положительный y и отрицательный x, второй и так далее. atan
или atan2
сами просто вернуть положительное или отрицательное число, не более того.
p=y/x
вы все еще можете использовать atan2(p,1)
.
Mehrwolf ниже верен, но вот эвристика, которая может помочь:
Если вы работаете в двумерной системе координат, которая часто используется для программирования обратной касательной, вы должны обязательно использовать atan2. Он даст полный диапазон углов 2 пи и позаботится о нулях в координате х.
Другой способ сказать, что atan (y / x) практически всегда неверен. Используйте atan, только если аргумент не может рассматриваться как y / x.
atan2(y,x)
обычно используется, если вы хотите преобразовать декартовы координаты в полярные координаты. Это даст вам угол, в то время как sqrt(x*x+y*y)
или, если доступно, hypot(y,x)
даст вам размер.
atan(x)
это просто обратный загар. В досадном случае вы должны использовать, atan(y/x)
потому что ваша система не обеспечивает atan2
, вам нужно будет сделать дополнительные проверки для признаков x
и y
, и, для x=0
того, чтобы получить правильный угол.
Примечание: atan2(y,x)
определяется для всех действительных значений y
и x
, за исключением случая, когда оба аргумента равны нулю.
В atan2, выход: -pi
< atan2(y,x)
< pi
и в Атан, выход: -pi/2
< atan(y/x)
< pi/2
// это доза не считают четверть.
Если вы хотите получить ориентацию между 0
и 2*pi
(например, по математике в старшей школе), нам нужно использовать atan2, а для отрицательных значений - добавить, 2*pi
чтобы получить окончательный результат между 0
и 2*pi
.
Вот исходный код Java, чтобы объяснить это ясно:
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
фактически включает одну точку (pi/2
) из квадранта II.