회전과 오일러 공식 직관
핵심 질문
복소수와 삼각함수는 어떻게 회전으로 연결될까?
교과서 설명
오일러 공식은 복소수와 삼각함수를 연결한다.
eiθ=cosθ+isinθ
이 식은 각도 θ만큼 회전한 단위원 위의 점을 복소수로 쓴 것이다.
음수 각도는 아래처럼 허수부의 부호가 바뀐다.
e−iθ=cosθ−isinθ
즉 eiθ가 반시계 방향 회전이라면, e−iθ는 같은 크기만큼 시계 방향으로 도는 회전이다. DFT의 지수에 −가 붙을 때도 이 반대 방향 회전을 사용한다.
일반 복소수는 길이와 각도로도 나타낼 수 있다.
z=r(cosθ+isinθ)=reiθ
여기서 r은 원점에서의 거리이고, θ는 방향 각도다. 복소수를 곱하면 길이는 곱해지고 각도는 더해진다.
r1eiα⋅r2eiβ=r1r2ei(α+β)
같은 회전을 여러 번 곱하면 각도도 그 횟수만큼 더해진다.
(eiθ)m=eimθ
그래서 DFT의 회전값도
e−2πikn/N=(e−2πi/N)kn
처럼 기본 회전값의 거듭제곱으로 정리할 수 있다.
좌표식으로 직접 곱하면 다음과 같다.
(a+bi)(c+di)=(ac−bd)+(ad+bc)i
이 공식이 “복소수 곱셈은 회전과 확대를 함께 한다”는 말을 계산으로 보여 준다.
난이도를 구분해 두자. 이 장에서는 오일러 공식을 깊게 증명하기보다, 삼각함수와 복소수 회전을 이어 주는 강력한 연결식으로 사용한다. 왜 정확히 성립하는지는 미분과 무한급수를 배운 뒤 더 엄밀하게 증명할 수 있다. 다음 증명 스케치는 선택적으로 읽어도 된다.
심화: 오일러 공식의 증명 스케치
대학 교재에서는 오일러 공식을 보통 거듭제곱급수로 유도한다. 지수함수, 사인, 코사인은 다음처럼 전개된다.
ex=1+x+2!x2+3!x3+⋯
cosx=1−2!x2+4!x4−⋯,sinx=x−3!x3+5!x5−⋯
여기서 x 대신 iθ를 넣으면
eiθ=1+iθ+2!(iθ)2+3!(iθ)3+4!(iθ)4+⋯
이다. i2=−1, i3=−i, i4=1을 이용해 실수부와 허수부를 따로 모으면
eiθ=(1−2!θ2+4!θ4−⋯)+i(θ−3!θ3+5!θ5−⋯)
가 된다. 앞 괄호는 cosθ, 뒤 괄호는 sinθ의 급수와 같으므로
eiθ=cosθ+isinθ
가 나온다. 이 증명은 고등학교 과정 밖의 무한급수를 사용하지만, 왜 지수함수와 회전이 연결되는지 보여 주는 가장 표준적인 길이다.
또한 오일러 공식은 회전의 합성 법칙과도 잘 맞는다.
eiαeiβ=ei(α+β)
즉 α만큼 돌고 다시 β만큼 도는 것은 한 번에 α+β만큼 도는 것과 같다. FFT의 회전 인자들이 거듭제곱으로 정리되는 이유도 이 성질에 기대고 있다.
직관 비유
eiθ는 회전 손잡이처럼 생각할 수 있다. 어떤 복소수에 이 값을 곱하면 그 복소수는 원점 중심으로 θ만큼 돌아간다.
예제
i는 90∘ 회전과 비슷하다.
1⋅i=i,i⋅i=−1
한 번 곱하면 위로 가고, 두 번 곱하면 왼쪽으로 간다.
예를 들어 1+i는 길이가 2이고 방향은 45∘이다. 여기에 i를 곱하면 방향이 90∘ 더 돌아간다.
(1+i)i=−1+i
손풀이 체크
-
ei0은 어떤 복소수일까?
답 보기
cos0+isin0=1
-
eiπ는 어떤 복소수일까?
답 보기
cosπ+isinπ=−1
-
길이 2, 각도 2π인 복소수는?
답 보기
2eiπ/2=2i
다음으로 이어지는 생각
DFT는 여러 회전 손잡이를 사용해서 신호 안에 숨어 있는 주파수를 찾는다.
eiθ=cosθ+isinθ를 회전 손잡이로 사용하기
#include <cmath>
#include <complex>
#include <iomanip>
#include <iostream>
using namespace std;
int main() {
const double pi = acos(-1.0);
double degrees = 90.0;
double theta = degrees * pi / 180.0;
complex<double> z(1, 1);
complex<double> rotation = polar(1.0, theta);
complex<double> result = rotation * z;
cout << fixed << setprecision(2);
cout << "rotated = " << result.real() << " + " << result.imag() << "i\n";
}
연습: θ=45∘,90∘,180∘로 바꿔서 회전 결과를 확인해 보자.