2009-03-12 9 views
3

(n,m)에서 (0,0)까지의 각도를 확인하려고합니다. arctan2을 사용할 수 없다면, m이 0 일 수 있다는 문제에 봉착했습니다. 0으로 나누면 0으로 나눌 수 있습니다.ARCTAN2 (n, m)의 편리 성없이 ARCTAN을 어떻게 다루어야합니까?

이 문제를 해결하기위한 우아하고 정확한 해결책은 무엇입니까?

+0

매우 오래된 프로그램 수렴 반각 식 arctan(x) = 2*arctan(x/(1+sqrt(1+x*x)))를 사용하여 절반 각도의 아크 탄젠트를 계산 계산자. – Kriem

답변

2

는 기존의 사분면을 사용하지 않는, y = +/- x 행으로 정의 된 분기점을 사용하고 CORDIC과 유사한 알고리즘의 첫 번째 두 단계를 사용합니다 (예 : 알려진 각도로 좌표를 회전하고 회전 한 양을 추적).

function atan2_substitute(x,y) 
{ 
    double angle = 0; 
    if (x < y) 
    { angle = M_PI; x = -x; y = -y; } 
    // this guarantees that the angle is between -135 and +45 degrees 

    if (x < -y) 
    { 
    angle -= M_PI/2; tmp = x; x = -y; y = tmp; 
    } 
    // this guarantees that the angle is between -45 and +45 

    angle += atan(y/x); 

    if (angle > M_PI) 
     angle -= 2*M_PI; 
    // fails at 0,0; otherwise is accurate over the entire plane 
} 

이렇게하는 이유는 atan()이 1보다 큰 비율보다 -1과 +1 사이의 y/x 비율에 대해 정확할 가능성이 높기 때문입니다. (좋은 atan() 알고리즘 m, n를 교환,

1) |m| < |n| 경우 :이 문제를 인식하고 테일러 시리즈를 사용하여 상호)

0

arctan2의 버전을 정의하십시오. 매크로 같은 C의 예는 : 물론

#define atan2(n,m) (m)==0 ? M_PI_2 : atan((n)/(m)) 

, 당신은 nm의 징후에 따라 사분면을 찾기위한 정교한 수 있습니다.

1

atan2를 사용할 수없는 경우 0으로 나누기 조건과 코드의 다른 모든 특수 사례를 확인해야합니다. 그것으로 간단합니다. atan2의 wikipedia 항목에는 필요한 모든 조건이 있습니다.

예외의 원인을 확인하는 낮은 수준의 처리기를 설치하고이되고 happends 경우 ATAN 부문이 문제를 해결 : 타겟 하드웨어 부동 소수점 연산 제로 예외로 분할을 지원하는 경우

다른 옵션이 있습니다. 예외가 드물지만 atan2가 더 빠르지 만 낮은 수준의 조작이 필요하고 이식성이 떨어지는 경우 atan2가 더 빠릅니다.

0

나는이 (비록, 무한대를 처리하지 않습니다) ATAN를 사용 ATAN2의 올바른 구현입니다 믿고 :

float my_atan2(float y, float x) 
{ 
    if(x == 0) // might also want to use fabs(x) < 1e-6 or something like that 
    { 
     if(y > 0) 
      return M_PI_2; 
     else 
      return -M_PI_2; 
    } 
    else if(x > 0) 
    { 
     return atan(y/x); 
    } 
    else 
    { 
     // x < 0                     
     if(y > 0) 
      return M_PI + atan(y/x); 
     else 
      return -M_PI + atan(y/x); 
    } 
} 

테스트 하네스 :

int main() 
{ 
    for(int i = -360; i <= 360; i++) 
    { 
     float x = cos(i/180.0 * M_PI); 
     float y = sin(i/180.0 * M_PI); 


     float good = atan2(y, x); 
     float mine = my_atan2(y, x); 


     if(fabs(good - mine) > 1e-6) 
     { 
      printf("%d %f %f %f %f\n", i, x, y, good, mine); 
     } 
    } 
} 
+0

x와 y가 모두 0이면? – truthseeker

+0

@truthseeker 그건 내가 "무한한 것을 다루지 않는다"는 의미입니다. 나는 그것이 일반적으로 정의되지 않은 것으로 간주되지만, 나는 atan2 워드 프로세서가 두 번째 인수의 부호에 따라 0 또는 pi로 정의됨을 알았다. –

1

구현 표준 arctan(n, m)을하고 계산 아크 탄젠트하기 전에 다음을 수행합니다 :

if (m == 0) { 
    if (n < 0) return Pi; 
    return 0; 
} 

또 다른 몇 가지 트릭을 그런 다음 arctan을 계산하십시오. 마지막 |n| 부근 Pi/2

2) |m| 경우의 결과를 감산 달리, 예컨대 값, 아크 탄젠트는 매우 느리게