Sự khác biệt nhỏ nhất giữa 2 góc


137

Cho 2 góc trong phạm vi -PI -> PI quanh tọa độ, giá trị nhỏ nhất của 2 góc giữa chúng là bao nhiêu?

Có tính đến sự khác biệt giữa PI và -PI không phải là 2 PI mà là không.

Thí dụ:

Hãy tưởng tượng một vòng tròn, với 2 đường thẳng xuất phát từ trung tâm, có 2 góc giữa các đường đó, góc chúng tạo ra ở bên trong hay còn gọi là góc nhỏ hơn và góc chúng tạo ra ở bên ngoài, hay còn gọi là góc lớn hơn. Cả hai góc khi thêm vào tạo thành một vòng tròn đầy đủ. Cho rằng mỗi góc có thể vừa trong một phạm vi nhất định, giá trị góc nhỏ hơn là gì, có tính đến cuộn qua


2
Tôi đã đọc 3 lần trước khi tôi hiểu ý của bạn. Vui lòng thêm một ví dụ hoặc giải thích rõ hơn ...
Kobi

Hãy tưởng tượng một vòng tròn, với 2 đường thẳng xuất phát từ tâm, có 2 góc giữa các đường đó, góc chúng tạo ra ở bên trong hay còn gọi là góc nhỏ hơn và góc chúng tạo ra ở bên ngoài, hay còn gọi là góc lớn hơn. Cả hai góc khi thêm vào tạo thành một vòng tròn đầy đủ. Cho rằng mỗi góc có thể vừa trong một phạm vi nhất định, giá trị góc nhỏ hơn là bao nhiêu, có tính đến cuộn qua
Tom J Nowell


2
@JimG. Đây không phải là cùng một câu hỏi, trong câu hỏi này, góc P1 được sử dụng trong câu hỏi kia sẽ là câu trả lời không chính xác, nó sẽ là góc kia, góc nhỏ hơn. Ngoài ra, không có gì đảm bảo rằng góc nằm với trục hoành
Tom J Nowell

Câu trả lời:


193

Điều này cung cấp một góc đã ký cho bất kỳ góc nào:

a = targetA - sourceA
a = (a + 180) % 360 - 180

Coi chừng trong nhiều ngôn ngữ, modulohoạt động trả về một giá trị có cùng dấu với cổ tức (như C, C ++, C #, JavaScript, danh sách đầy đủ ở đây ). Điều này đòi hỏi một modchức năng tùy chỉnh như vậy:

mod = (a, n) -> a - floor(a/n) * n

Hoặc là:

mod = (a, n) -> (a % n + n) % n

Nếu các góc nằm trong [-180, 180] thì điều này cũng hoạt động:

a = targetA - sourceA
a += (a>180) ? -360 : (a<-180) ? 360 : 0

Theo một cách dài dòng hơn:

a = targetA - sourceA
a -= 360 if a > 180
a += 360 if a < -180

Đơn giản hơn và có ý nghĩa hơn khi đọc thành tiếng, mặc dù thực tế là điều tương tự, đầu tiên bti tìm ra góc, phần thứ hai đảm bảo nó luôn nhỏ hơn trong 2 góc có thể
Tom J Nowell

1
mặc dù người ta có thể muốn thực hiện% 360, ví dụ: nếu tôi có góc 0 và góc mục tiêu 721, câu trả lời đúng sẽ là 1, câu trả lời được đưa ra ở trên sẽ là 361
Tom J Nowell

1
Một cách ngắn gọn hơn, mặc dù có khả năng đắt hơn, tương đương với tuyên bố thứ hai của phương pháp sau, là a -= 360*sgn(a)*(abs(a) > 180). (Nghĩ về nó, nếu bạn không triển khai thực hiện sgnabs, thì đặc điểm đó thực sự có thể bắt đầu bù cho việc cần hai phép nhân.)
mmirate

1
Ví dụ "Góc đã ký cho bất kỳ góc nào" dường như hoạt động trong hầu hết các trường hợp, với một ngoại lệ. Trong kịch bản double targetA = 2; double sourceA = 359;'a' sẽ bằng -357.0 thay vì 3.0
Stevoisiak

3
Trong C ++, bạn có thể sử dụng std :: fmod (a, 360) hoặc fmod (a, 360) để sử dụng modulo dấu phẩy động.
Joeppie

145

x là góc mục tiêu. y là nguồn hoặc góc bắt đầu:

atan2(sin(x-y), cos(x-y))

Nó trả về góc delta đã ký. Lưu ý rằng tùy thuộc vào API của bạn, thứ tự của các tham số cho hàm atan2 () có thể khác nhau.


13
x-ycung cấp cho bạn sự khác biệt về góc, nhưng nó có thể nằm ngoài giới hạn mong muốn. Hãy nghĩ về góc này xác định một điểm trên vòng tròn đơn vị. Các tọa độ của điểm đó là (cos(x-y), sin(x-y)). atan2trả về góc cho điểm đó (tương đương với x-y) ngoại trừ phạm vi của nó là [-PI, PI].
Tối đa

3
Điều này vượt qua bộ thử nghiệm gist.github.com/bradphelan/7fe21ad8ebfcb43696b8
bradgonesurfing 13/07/2015

2
một giải pháp đơn giản và giải quyết cho tôi (không phải câu trả lời được chọn;)). nhưng tan nghịch đảo là một quá trình tốn kém.
Mohan Kumar

2
Đối với tôi, giải pháp thanh lịch nhất. Xấu hổ vì nó có thể đắt tiền.
focs

Đối với tôi giải pháp thanh lịch nhất là tốt! Đã giải quyết vấn đề của tôi một cách hoàn hảo (muốn có một công thức cho tôi góc quay được , đó là góc nhỏ hơn từ hai hướng / góc quay có thể).
Jürgen Brauer

41

Nếu hai góc của bạn là x và y, thì một trong các góc giữa chúng là abs (x - y). Góc còn lại là (2 * PI) - abs (x - y). Vậy giá trị nhỏ nhất của 2 góc là:

min((2 * PI) - abs(x - y), abs(x - y))

Điều này cung cấp cho bạn giá trị tuyệt đối của góc và nó giả sử các đầu vào được chuẩn hóa (nghĩa là: trong phạm vi [0, 2π)).

Nếu bạn muốn giữ dấu (ví dụ: hướng) của góc và cũng chấp nhận các góc ngoài phạm vi, [0, 2π)bạn có thể khái quát hóa ở trên. Đây là mã Python cho phiên bản tổng quát:

PI = math.pi
TAU = 2*PI
def smallestSignedAngleBetween(x, y):
    a = (x - y) % TAU
    b = (y - x) % TAU
    return -a if a < b else b

Lưu ý rằng %toán tử không hoạt động giống nhau trong tất cả các ngôn ngữ, đặc biệt là khi các giá trị âm có liên quan, do đó, nếu chuyển một số điều chỉnh dấu hiệu có thể là cần thiết.


1
@bradgonesurfing Điều đó đúng / là đúng, nhưng để công bằng các bài kiểm tra của bạn đã kiểm tra những thứ không được chỉ định trong câu hỏi ban đầu, cụ thể là đầu vào không được chuẩn hóa và bảo quản dấu hiệu. Phiên bản thứ hai trong câu trả lời được chỉnh sửa sẽ vượt qua bài kiểm tra của bạn.
Laurence Gonsalves

Phiên bản thứ hai cũng không hoạt động với tôi. Hãy thử 350 và 0 chẳng hạn. Nó sẽ trả về -10 nhưng trả về -350
kjyv

@kjyv Tôi không thể tái tạo hành vi bạn mô tả. Bạn có thể gửi mã chính xác?
Laurence Gonsalves

À, tôi xin lỗi. Tôi đã kiểm tra chính xác phiên bản của bạn với rad và độ trong python một lần nữa và nó hoạt động tốt. Vì vậy, đã có một lỗi trong bản dịch của tôi sang C # (không có nó nữa).
kjyv

2
Lưu ý rằng, kể từ Python 3, bạn thực sự có thể sử dụng tau nguyên bản! Chỉ cần viết from math import tau.
mhartl

8

Tôi vượt qua thách thức cung cấp câu trả lời đã ký:

def f(x,y):
  import math
  return min(y-x, y-x+2*math.pi, y-x-2*math.pi, key=abs)

1
À ... câu trả lời là một hàm Python. Xin lỗi, tôi đã ở chế độ Python một lát. Hy vọng là ổn.
David Jones

Tôi sẽ cắm công thức mới vào mã của tôi ở tầng trên và xem những gì trở thành của nó! (cảm ơn ^ _ ^)
Tom J Nowell

1
Tôi khá chắc chắn câu trả lời của PeterB cũng đúng. Và evilly hackish. :)
David Jones

4
Nhưng cái này không chứa chức năng trig :)
nornagon

Công thức tương đương cho java là gì? nếu các góc là độ.?
Soley



2

Một mã hiệu quả trong C ++ hoạt động cho mọi góc độ và cả hai: radian và độ là:

inline double getAbsoluteDiff2Angles(const double x, const double y, const double c)
{
    // c can be PI (for radians) or 180.0 (for degrees);
    return c - fabs(fmod(fabs(x - y), 2*c) - c);
}

-1

Không cần phải tính các hàm lượng giác. Mã đơn giản trong ngôn ngữ C là:

#include <math.h>
#define PIV2 M_PI+M_PI
#define C360 360.0000000000000000000
double difangrad(double x, double y)
{
double arg;

arg = fmod(y-x, PIV2);
if (arg < 0 )  arg  = arg + PIV2;
if (arg > M_PI) arg  = arg - PIV2;

return (-arg);
}
double difangdeg(double x, double y)
{
double arg;
arg = fmod(y-x, C360);
if (arg < 0 )  arg  = arg + C360;
if (arg > 180) arg  = arg - C360;
return (-arg);
}

Đặt Dif = a - b, tính bằng radian

dif = difangrad(a,b);

Đặt Dif = a - b, tính bằng độ

dif = difangdeg(a,b);

difangdeg(180.000000 , -180.000000) = 0.000000
difangdeg(-180.000000 , 180.000000) = -0.000000
difangdeg(359.000000 , 1.000000) = -2.000000
difangdeg(1.000000 , 359.000000) = 2.000000

Không tội lỗi, không cos, không tan, .... chỉ hình học !!!!


7
Bọ cánh cứng! Vì bạn #define PIV2 là "M_PI + M_PI", chứ không phải "(M_PI + M_PI)", dòng arg = arg - PIV2;mở rộng thành arg = arg - M_PI + M_PIvà không có gì.
cant7
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.