파이썬 Decimal 모듈에서의 삼각함수 구현
파이썬 Decimal 모듈 에서는 로그함수, 지수함수 등은 지원하지만 삼각함수는 지원하지 않습니다.
따라서 개인용으로 쓸 Decimal 삼각함수를 구현해둡니다.
(이 자료는 개인적인 용도로 제공되는 것으로, 전문적인 용도로 사용할 경우에 대한 책임은 사용자에게 있습니다.)
0. 전략
테일러 급수 를 이용해줍니다.
(미분방정식을 이용해서 수치해석적으로 푸는 방법도 있을 것입니다. $\sin x$는 $y'' + y = 0$, $y(0) = 0$, $y'(0) = 1$을 풀고, $\cos x$는 $y'' + y = 0$, $y(0) = 1$, $y'(0) = 0$를 풀면 됩니다.)
어지간한 상황에서 $x^{n}$꼴이 나오므로, $x < 1$이면 그나마 괜찮지만 $x > 1$이면 $x^{n}$이 너무 커질 우려가 있으니 삼각함수의 특징들을 이용하여 계산하는 $x$를 최대한 $1$ 아래로 줄여줍니다.
사인함수와 코사인함수는 $2\pi$를 주기로 가지므로, 매개변수로 들어온 $x$의 절댓값이 $2\pi$를 초과하면 나머지 연산자를 사용해서 sin(x % 2pi)를 대신 계산합니다.
그래도 $x$의 절댓값이 $6$가량이 될 수 있으므로, $x$의 절댓값이 아직 $1$을 넘는다면 삼각함수의 덧셈정리 를 이용해서 $\sin(x) = \sin\left(\frac{x}{2}\right) \times \cos\left(\frac{x}{2}\right)$ 을 계산해줍니다.
그리고나면 평범하게 테일러 급수로 $\sin x = \sum_{n = 0}^{\infty} \frac{{(-1)}^{n}}{(2n + 1)!} x^{2n + 1}$, $\cos x = \sum_{n = 0}^{\infty} \frac{{(-1)}^{n}}{(2n)!} x^{2n}$를 이용해줍니다.
1. 사인함수 / 코사인함수
조금 더 축약해서 쓸 수 있습니다.
% 2 는 & 1과 (음이 아닌 정수 연산에서는) 동치임을 이용한 코드입니다.
만약 $2\pi$로 나눈 나머지에 대해서만 구하는 부분을 제거한다면 sin(1000000) 정도 넣으면 절댓값이 1을 넘어버리는 진귀한 풍경을 볼 수 있습니다.
탄젠트함수 는? 사인함수를 코사인함수로 나눠줍니다.
탄젠트 함수를 테일러 급수로 구하려면 베르누이 수 라는것을 계산해야하는데, 이거 계산할 시간에 그냥 사인 코사인 계산해서 사인 / 코사인을 return 하는게 훨씬 더 빠릅니다.
2. 아크탄젠트함수
탄젠트 함수의 역함수인 아크탄젠트 함수는 사인, 코사인, 탄젠트 함수를 이용해서 이분탐색으로 찾아줄 수도 있겠지만 그냥 넣으면 바로 답을 뱉어주는 코드를 원할 수 있습니다.
다음과 같은 3개의 항등식을 이용해줍니다.
1. $\arctan x = \sum_{n = 0}^{\infty} \frac{{(-1)}^{n} x^{2n + 1}}{2n + 1} \quad (|x| \leq 1)$
2. $x > 0$이면 $\arctan(x) + \arctan\left(\frac{1}{x}\right) = \frac{\pi}{2}$
3. $x < 0$이면 $\arctan(x) + \arctan\left(\frac{1}{x}\right) = -\frac{\pi}{2}$
사인, 코사인처럼 더 축약할 수 있습니다.
2 - 1. atan2(y, x)
x축의 양의 방향에서 점 (x, y)까지의 각도를 측정하는 함수입니다. 아크탄젠트를 약간 조절하면 됩니다.
백준 13705번 - Ax+Bsin(x)=C 같은 문제에서 사용할 수 있습니다.