상세 컨텐츠

본문 제목

역삼각함수를 구현해보자.

프로그래밍/테크닉

by ∫2tdt=t²+c 2008. 12. 8. 00:07

본문

하아 어느덧 여러 수학함수를 구현해보려는 기나긴 장정이 역삼각함수에까지 이르렀다. 아직 쌍곡선 함수를 비롯한 여러 수학함수들이 남아있지만, 거의 쓰이지 않는 관계로(또한 귀찮은 관계로) 글쓰기를 무기한 연기해버리기로 했다.
역삼각함수는 각을 구해내기 위해서 자주 쓰인다. acos,asin,atan 등이 있지만, 가장 유용한 함수는 atan2이다. atan2는 x축 변위,y축 변위를 받아서 -Pi에서 Pi 사이의 각을 구해준다. (acos,asin,atan함수는 제한된 범위의 각만 구해낼수 있다.) 일단 atan2함수도 atan를 이용해 구현될수 있으므로 좀 뒤로 미루자.

먼저 역시 방대한 지식이 담겨있는 위키백과만큼 좋은 참조물도 없다. 영어위키백과: 역삼각함수

역삼각함수들에 대해서 다음 등식이 성립한다.
http://www.sitmo.com/gg/latex/latex2png.2.php?z=100&eq=%5Carcsin%20x%3D%5Carctan%20%5Cfrac%7Bx%7D%7B%5Csqrt%7B1-x%5E2%7D%7D
http://www.sitmo.com/gg/latex/latex2png.2.php?z=100&eq=%5Carccos%20x%3D%5Cfrac%7B%5Cpi%7D%7B2%7D-%5Carcsin%20x (자명한 등식이다. 삼각함수의 성질을 이용하면 간단하게 증명할수 있다.)
따라서 asin,acos모두 atan를 이용해 구할수 있다.

그럼 atan를 한 번 테일러 전개해보자.
http://www.sitmo.com/gg/latex/latex2png.2.php?z=100&eq=%5Carctan%20x%3Dx-%5Cfrac%7Bx%5E3%7D%7B3%7D%2B%5Cfrac%7Bx%5E5%7D%7B5%7D-%5Cfrac%7Bx%5E7%7D%7B7%7D%2B%5Cldots (단, |x|<=1)
저번에 로그함수를 테일러전개했을때 처럼 부호가 번갈아 나온다. 게다가 분모가 증가하는 속도도 굉장히 느리다. 거의 치명적인 수렴속도다.
게다가 아크탄젠트 함수는 인수로 (-∞,∞)의 범위의 수가 들어온다. 그런데 수렴범위는 |x|<=1이므로, 나머지는 어떻게 할 도리가 없다.
이때 등장한 구원의 손길!!!
http://www.sitmo.com/gg/latex/latex2png.2.php?z=100&eq=%5Carctan%20x%3D%5Cfrac%7B%5Cpi%7D%7B2%7D-%5Carctan%5Cfrac%7B1%7D%7Bx%7D(단 x는 양수)
http://www.sitmo.com/gg/latex/latex2png.2.php?z=100&eq=%5Carctan(-x)%3D-%5Carctan%20x
이 공식을 통하면 1보다 큰 실수의 아크탄젠트값도 구할수 있다. (역수를 취하면 1보다 작아지므로 테일러 전개식의 수렴범위 안에 포함된다.)
하지만 아직 수렴속도 문제는 해결되지 않았다. 이 때 수학자들이 테일러 전개 말고 새로운 계산법인 연분수식을 선물한다.
http://www.sitmo.com/gg/latex/latex2png.2.php?z=100&eq=%5Carctan(z)%3D%5Ccfrac%7Bz%7D%7B1%20%2B%20%5Ccfrac%7Bz%5E2%7D%7B3%20%2B%20%5Ccfrac%7B4%20z%5E2%7D%7B5%20%2B%20%5Ccfrac%7B9%20z%5E2%7D%7B7%20%2B%20%5Ccfrac%7B16%20z%5E2%7D%7B9%20%2B%20%5Ccfrac%7B25%20z%5E2%7D%7B%5Cddots%7D%7D%7D%7D%7D%7D
정말 아름다운 식이다. 어떻게 이런 식이 나오는지 궁금하다면 혼자서 공부해보시길(필자는 설명할 능력이 부족하다.) 수학자들이 말하길 이 식은 모든 z에 대해서 성립한다고 (하지만 |z|<=1 구간에서 더 빨리 수렴한다) 한다.
이제 그저 이 식에 대입만 해서 아크탄젠트 값을 구하면 된다.
만약 연분수식이 싫다는 사람들을 위해서 또 다른 방법을 준비했다.

역삼각함수의 성질 중에서 다음과 같은게 있다.
http://www.sitmo.com/gg/latex/latex2png.2.php?z=100&eq=%5Carctan%20x%3D2%5Carctan%5Cfrac%7Bx%7D%7B%5Csqrt%7B1%2Bx%5E2%7D%2B1%7D(모든 x에 대해 성립한다.)
이때 머리 한쪽에서 부동소수점 데이터 형식에 관한 정보가 번쩍인다. 2를 곱하는 것은 부동소수점의 지수부를 1늘리는 것이므로 공짜라고 볼 수 있다. 그런데
http://www.sitmo.com/gg/latex/latex2png.2.php?z=100&eq=%5Cfrac%7Bx%7D%7B%5Csqrt%7B1%2Bx%5E2%7D%2B1%7D는 항상 x보다 0에 훨~씬 가깝다.
만약 위의 식을 수십번 반복하면 아무리 큰 x라도 거의 0에 가까워진다. 이 때
http://www.sitmo.com/gg/latex/latex2png.2.php?z=100&eq=%5Carctan%20x%3Dx-%5Cfrac%7Bx%5E3%7D%7B3%7D%2B%5Cfrac%7Bx%5E5%7D%7B5%7D-%5Cfrac%7Bx%5E7%7D%7B7%7D%2B%5Cldots
이 테일러 전개식을 활용해 계산한다면 x의 세제곱 이상의 항들은 아예 0에 가까워져서 계산하나마나 별 효과가 없을 것이므로,
http://www.sitmo.com/gg/latex/latex2png.2.php?z=100&eq=%5Carctan%20x%5Capprox%20x(0에 매우 가까운 x에 대해)
따라서
http://www.sitmo.com/gg/latex/latex2png.2.php?z=100&eq=%5Carctan%20x%3D2%5Carctan%5Cfrac%7Bx%7D%7B%5Csqrt%7B1%2Bx%5E2%7D%2B1%7D 이 식을 이용해 구해야하는 인수 값을 0에 충분히 가깝게 보내고 그때 http://www.sitmo.com/gg/latex/latex2png.2.php?z=100&eq=%5Carctan%20x%5Capprox%20x를 써서 계산하면 된다.

다만 이 방법의 문제점은 제곱근 연산을 해야한다는 것인데, 제곱근이 결코 싼 함수는 아니므로, 적당히 이 방법으로 인수를 0에 가까이 보내서 위에서 설명한 연분수 방법을 쓰는 것이 최적의 해법이랍니다.(위키백과曰)
그런데 사실 삼각함수와 마찬가지로 가장 빠른 방법은 테이블을 참조하는 것이다.(ㅋㅋ)

관련글 더보기

댓글 영역