Sự khác biệt giữa atan và atan2 trong C ++ là gì?


156

Sự khác biệt giữa atanatan2trong C ++ là gì?

Câu trả lời:



321

Từ toán học ở trường, chúng ta biết rằng tiếp tuyến có định nghĩa

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

và chúng tôi phân biệt giữa bốn góc phần tư dựa trên góc mà chúng tôi cung cấp cho các hàm. Các dấu hiệu của sin, costancó mối quan hệ sau (nơi chúng tôi bỏ qua bội chính xác của π/2):

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

Cho rằng giá trị của tan(α)là dương, chúng ta không thể phân biệt được, cho dù góc đó là góc phần tư thứ nhất hay thứ ba và nếu nó âm, nó có thể đến từ góc phần tư thứ hai hoặc thứ tư. Vì vậy, theo quy ước, atan()trả về một góc từ góc phần tư thứ nhất hoặc thứ tư (nghĩa là -π/2 <= atan() <= π/2), bất kể đầu vào ban đầu đến tiếp tuyến.

Để lấy lại thông tin đầy đủ, chúng ta không được sử dụng kết quả của phép chia sin(α) / cos(α)mà chúng ta phải xem xét riêng các giá trị của sin và cosin. Và đây là những gì atan2()không. Nó cần cả hai, sin(α)cos(α)và giải quyết cả bốn góc phần tư bằng cách thêm πvào kết quả của atan()bất cứ khi nào cosin âm.

Ghi chú: Các atan2(y, x)chức năng thực sự mất một yvà một xtham số, đó là dự báo của một vector có chiều dài vvà góc αtrên Y- và trục x, tức là

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

cung cấp cho các mối quan hệ

y/x = tan(α)

Kết luận: atan(y/x) được giữ lại một số thông tin và chỉ có thể giả sử rằng đầu vào đến từ góc phần tư I hoặc IV. Ngược lại, atan2(y,x)có được tất cả các dữ liệu và do đó có thể giải quyết các góc chính xác.


3
Một chi tiết nhỏ, phạm vi -π/2 <= atan() <= π/2thực sự bao gồm một điểm ( pi/2) từ góc phần tư II.
Z boson

28

Một điều khác cần đề cập là atan2ổn định hơn khi tính toán các tiếp tuyến sử dụng một biểu thức như atan(y / x)và bằng x0 hoặc gần bằng 0.


Thật thú vị, bạn có một nguồn cho việc này? Điều này nói chung đúng hay chỉ dành cho C ++?
Gerard

26

Các giá trị thực tế được tính bằng radian nhưng để giải thích chúng theo độ sẽ là:

  • atan = đưa ra giá trị góc giữa -90 và 90
  • atan2 = đưa ra giá trị góc giữa -180 và 180

Đối với công việc của tôi liên quan đến việc tính toán các góc độ khác nhau như tiêu đề và mang trong điều hướng, atan2trong hầu hết các trường hợp thực hiện công việc.


12

atan (x) Trả về giá trị chính của tiếp tuyến cung của x, được biểu thị bằng radian.

atan2 (y, x) Trả về giá trị chính của tiếp tuyến cung của y / x, được biểu thị bằng radian.

Lưu ý rằng do sự không rõ ràng của dấu hiệu, một hàm không thể xác định chắc chắn trong đó góc phần tư chỉ rơi bởi giá trị tiếp tuyến của nó (một mình atan). Bạn có thể sử dụng atan2 nếu bạn cần xác định góc phần tư.


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

Phạm vi của các giá trị nguyên tắc là (-pi,pi]nhưng atan2 có phạm vi [-pi,pi]để nó bao gồm một giá trị tăng thêm -pitừ chi nhánh khác do atan2(-0.0,x)cho x<0.
Z boson

4

Tôi đoán câu hỏi chính cố gắng tìm ra: "khi nào tôi nên sử dụng cái này hay cái kia", hay "tôi nên sử dụng cái nào" hay "Tôi có nên sử dụng đúng không"?

Tôi đoán rằng điểm quan trọng là atan chỉ nhằm mục đích cung cấp các giá trị dương theo đường cong hướng lên phải như đối với các vectơ khoảng cách thời gian. Cero luôn ở phía dưới bên trái, và những người chơi chỉ có thể đi lên và sang phải, chỉ chậm hơn hoặc nhanh hơn. atan không trả về số âm, vì vậy bạn không thể theo dõi mọi thứ theo 4 hướng trên màn hình chỉ bằng cách thêm / bớt kết quả của nó.

atan2 được dự định cho nguồn gốc ở giữa và mọi thứ có thể đi lùi hoặc xuống. Đó là những gì bạn sử dụng trong một đại diện màn hình, bởi vì nó không quan trọng bạn muốn đường cong đi theo hướng nào. Vì vậy, atan2 có thể cung cấp cho bạn các số âm, vì cero của nó nằm ở trung tâm và kết quả của nó là thứ bạn có thể sử dụng để theo dõi mọi thứ theo 4 hướng.


2

Với atan2, bạn có thể xác định góc phần tư như đã nêu ở đây .

Bạn có thể sử dụng atan2 nếu bạn cần xác định góc phần tư.


2

Xét một tam giác góc vuông. Chúng tôi dán nhãn hypotenuse r, mặt ngang y và mặt đứng x. Góc quan tâm α là góc giữa x và r.

C ++ atan2(y, x)sẽ cho chúng ta giá trị của góc α tính bằng radian. atanđược sử dụng nếu chúng ta chỉ biết hoặc quan tâm đến y / x chứ không phải y và x riêng lẻ. Vì vậy, nếu p = y / x thì để có được chúng tôi sẽ sử dụng atan(p).

Bạn không thể sử dụng atan2để xác định góc phần tư, bạn chỉ có thể sử dụng atan2nếu bạn đã biết góc phần tư của bạn trong! Cụ thể là dương x và y ngụ ý góc phần tư thứ nhất, y dương và âm x, thứ hai, v.v. atanhoặc atan2bản thân họ chỉ đơn giản trả về một số dương hoặc một số âm, không có gì hơn.


4
Nếu tất cả những gì bạn có là p=y/xbạn vẫn có thể sử dụng atan2(p,1).
Đánh dấu tiền chuộc

0

Mehrwolf dưới đây là chính xác, nhưng đây là một heuristic có thể giúp:

Nếu bạn đang làm việc trong một hệ tọa độ 2 chiều, thường là trường hợp để lập trình tiếp tuyến nghịch đảo, bạn nên sử dụng chắc chắn sử dụng atan2. Nó sẽ cung cấp phạm vi 2 góc đầy đủ và chăm sóc các số 0 trong tọa độ x cho bạn.

Một cách khác để nói điều này là atan (y / x) hầu như luôn luôn sai. Chỉ sử dụng atan nếu đối số không thể được coi là y / x.


0

atan2(y,x)thường được sử dụng nếu bạn muốn chuyển đổi tọa độ cartesian sang tọa độ cực. Nó sẽ cung cấp cho bạn các góc, trong khi sqrt(x*x+y*y)hoặc, nếu có, hypot(y,x)sẽ cung cấp cho bạn kích thước.

atan(x)chỉ đơn giản là nghịch đảo của tan. Trong trường hợp gây phiền nhiễu bạn phải sử dụng atan(y/x)vì hệ thống của bạn không cung cấp atan2, bạn sẽ phải kiểm tra bổ sung các dấu hiệu xy, và x=0, để có được góc chính xác.

Lưu ý: atan2(y,x) được xác định cho tất cả các giá trị thực của yx, ngoại trừ trường hợp khi cả hai đối số đều bằng không.


0

Trong atan2, đầu ra là: -pi< atan2(y,x)< pi
và trong atan, đầu ra là: -pi/2< atan(y/x)< pi/2 // nó liều KHÔNG cân nhắc quý.
Nếu bạn muốn có được định hướng giữa 02*pi(như toán học trung học), chúng ta cần sử dụng atan2 và cho các giá trị âm thêm vào 2*piđể có kết quả cuối cùng giữa 02*pi.
Đây là mã nguồn Java để giải thích rõ ràng:

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.