Ch.8 §8.5 Fourier Series — 함수 공간에서의 선형대수

무한차원 직교 기저·푸리에 계수·Parseval 정리·사각파와 라이프니츠 급수

푸리에 급수는 선형대수를 무한차원으로 확장한 것이다. 벡터를 함수로, 합을 적분으로 바꾸면 내적·직교성·정사영이 그대로 살아남는다. sin/cos가 왜 직교 기저인지, 푸리에 계수가 왜 내적인지, Parseval 정리가 왜 길이 보존인지를 유한차원 대응물과 나란히 전개한다 (Strang, 2009, §8.5).

Math
Linear Algebra
저자

Kwangmin Kim

공개

2026년 04월 12일

1 개요: 유한에서 무한으로 — 바뀌는 것과 바뀌지 않는 것

Ch.1~7에서 배운 선형대수의 핵심 도구 — 내적, 직교성, 정사영, 정규직교 기저, \(Q^\top Q = I\) — 는 \(\mathbb{R}^n\) 에서만 작동하는가? 아니다. \(n\) 을 무한대로 보내도 이 도구들은 거의 그대로 살아남는다. §8.5는 이 사실을 푸리에 급수를 통해 보여준다 (Strang, 2009, §8.5).

바뀌는 것은 단 하나 — 합이 적분으로 바뀐다. 나머지는 유한차원과 판박이다.

핵심 직관

유한차원에서 벡터 \(\mathbf{b}\) 를 직교 기저 \(\{\mathbf{v}_1, \ldots, \mathbf{v}_n\}\) 으로 분해할 때

\[ \mathbf{b} = c_1 \mathbf{v}_1 + c_2 \mathbf{v}_2 + \cdots + c_n \mathbf{v}_n, \quad c_k = \frac{\mathbf{v}_k^\top \mathbf{b}}{\mathbf{v}_k^\top \mathbf{v}_k} \]

무한차원에서 함수 \(f(x)\) 를 직교 기저 \(\{1, \cos x, \sin x, \cos 2x, \sin 2x, \ldots\}\) 으로 분해할 때

\[ f(x) = a_0 + \sum_{k=1}^{\infty}(a_k \cos kx + b_k \sin kx), \quad a_k = \frac{\int f(x) \cos kx \, dx}{\int \cos^2 kx \, dx} \]

구조가 동일하다. 분자는 내적, 분모는 길이의 제곱이다.

2 무한차원 벡터: 두 가지 관점

무한 개의 성분을 가진 벡터는 두 가지 형태로 나타난다 (Strang, 2009, §8.5).

관점 1: 무한 수열

\[ \mathbf{v} = (v_1, v_2, v_3, \ldots) \]

예를 들어 \(\mathbf{v} = (1, \tfrac{1}{2}, \tfrac{1}{4}, \ldots)\) 은 성분이 무한히 이어지는 벡터다.

관점 2: 함수

\[ f(x) \quad \text{(예: } f(x) = \sin x\text{)} \]

함수 \(f(x)\) 는 각 \(x\) 값에 대해 하나의 “성분”을 주므로, 연속적으로 무한 개의 성분을 가진 벡터로 볼 수 있다. 푸리에 급수가 이 두 관점을 연결한다 — 함수 \(f(x)\) 와 그 푸리에 계수 벡터 \((a_0, a_1, b_1, a_2, b_2, \ldots)\) 가 일대일 대응한다.

3 무한차원의 내적과 길이

3.1 수열 벡터의 경우

유한차원에서 \(\mathbf{v} \cdot \mathbf{w} = v_1 w_1 + v_2 w_2 + \cdots + v_n w_n\) 이었다. 무한차원에서는 합이 무한급수가 된다.

\[ \mathbf{v} \cdot \mathbf{w} = v_1 w_1 + v_2 w_2 + v_3 w_3 + \cdots \]

유한차원에서는 없던 문제가 등장한다 — 이 무한 합이 수렴하는가? \(\mathbf{v} = \mathbf{w} = (1, 1, 1, \ldots)\) 이면 \(\mathbf{v} \cdot \mathbf{v} = 1 + 1 + 1 + \cdots = \infty\) 다. 이 벡터는 “길이가 무한”하므로 사용할 수 없다.

정의: 힐베르트 공간 (Hilbert Space)

무한 수열 벡터 \(\mathbf{v} = (v_1, v_2, \ldots)\) 가 힐베르트 공간에 속하려면, 그 길이가 유한해야 한다.

\[ \|\mathbf{v}\|^2 = v_1^2 + v_2^2 + v_3^2 + \cdots < \infty \]

이 조건을 만족하는 수열들의 집합을 \(\ell^2\) 라고 쓴다.

예를 들어 \(\mathbf{v} = (1, \tfrac{1}{2}, \tfrac{1}{4}, \ldots)\) 의 길이의 제곱은 등비급수다.

\[ \|\mathbf{v}\|^2 = 1 + \frac{1}{4} + \frac{1}{16} + \cdots = \frac{1}{1 - 1/4} = \frac{4}{3} \]

이 벡터는 길이가 \(2/\sqrt{3}\) 으로 유한하므로 힐베르트 공간에 속한다. 반면 \((1, 1, 1, \ldots)\) 은 길이가 무한하므로 힐베르트 공간에서 추방된다.

Strang의 핵심 관찰: 유한 길이의 벡터 두 개의 내적은 반드시 유한하다. 코시-슈바르츠 부등식이 무한차원에서도 성립한다.

\[ |\mathbf{v} \cdot \mathbf{w}| \leq \|\mathbf{v}\| \cdot \|\mathbf{w}\| \]

3.2 함수의 경우: 합을 적분으로

함수 공간에서는 합이 적분으로 바뀐다. 두 함수 \(f(x)\)\(g(x)\) 의 내적과 길이를 다음과 같이 정의한다.

정의: 함수 공간의 내적과 길이

\([0, 2\pi]\) 에서 정의된 함수에 대해:

\[ (f, g) = \int_0^{2\pi} f(x) g(x) \, dx \quad \text{(내적)} \]

\[ \|f\|^2 = \int_0^{2\pi} [f(x)]^2 \, dx \quad \text{(길이의 제곱)} \]

구간 \([0, 2\pi]\) 을 선택한 이유는 \(\sin x\)\(\cos x\) 의 주기가 \(2\pi\) 이기 때문이다. 다른 구간(예: \([0, 1]\) 이나 \((-\infty, \infty)\))을 쓸 수도 있다.

3.3 유한차원-무한차원 대응표

이 대응은 §8.5의 골격이다. 왼쪽의 모든 정리가 오른쪽에서도 성립한다.

유한차원 \(\mathbb{R}^n\) 무한차원 함수 공간 \(L^2[0, 2\pi]\)
벡터 \(\mathbf{v} = (v_1, \ldots, v_n)\) 함수 \(f(x)\)
내적 \(\mathbf{v}^\top \mathbf{w} = \sum_{i=1}^n v_i w_i\) \((f, g) = \int_0^{2\pi} f(x) g(x) \, dx\)
길이 \(\|\mathbf{v}\|^2 = \sum v_i^2\) \(\|f\|^2 = \int [f(x)]^2 \, dx\)
직교 \(\mathbf{v}^\top \mathbf{w} = 0\) \(\int f(x) g(x) \, dx = 0\)
정규직교 기저 \(Q\), \(Q^\top Q = I\) \(\{1, \cos x, \sin x, \cos 2x, \sin 2x, \ldots\}\) (정규화 후)
좌표 \(c_k = \mathbf{v}_k^\top \mathbf{b} / \mathbf{v}_k^\top \mathbf{v}_k\) 푸리에 계수 \(a_k = \frac{1}{\pi}\int f(x)\cos kx \, dx\)
길이 보존 \(\|\mathbf{b}\|^2 = \sum c_k^2 \|\mathbf{v}_k\|^2\) Parseval: \(\|f\|^2 = 2\pi a_0^2 + \pi \sum(a_k^2 + b_k^2)\)

이 표를 통째로 외우면 푸리에 급수의 모든 공식이 “당연한” 것이 된다.

4 sin과 cos의 직교성: 왜 이 기저가 특별한가

4.1 직교성 증명

\(\sin nx\)\(\cos mx\)\([0, 2\pi]\) 에서 서로 직교한다. 이것은 삼각함수의 곱-합 공식(product-to-sum identity)에서 바로 나온다.

\[ 2\cos jx \cos kx = \cos(j+k)x + \cos(j-k)x \]

양변을 \([0, 2\pi]\) 에서 적분하면, \(j \neq k\) 일 때 오른쪽의 두 항 모두 완전한 주기의 적분이므로 0이 된다.

\[ \int_0^{2\pi} \cos jx \cos kx \, dx = 0 \quad (j \neq k) \]

같은 논리로 다음이 모두 성립한다.

\[ \int_0^{2\pi} \sin jx \sin kx \, dx = 0 \quad (j \neq k) \]

\[ \int_0^{2\pi} \sin jx \cos kx \, dx = 0 \quad (\text{모든 } j, k) \]

왜 sin-cos 내적은 \(j = k\) 일 때도 0인가? \(\sin jx \cos jx = \frac{1}{2}\sin 2jx\) 이고, 이것의 \([0, 2\pi]\) 적분은 완전한 주기이므로 역시 0이다.

4.2 각 기저 함수의 길이

기저 함수 \(\int_0^{2\pi} [\cdot]^2 \, dx\) 길이
\(1\) (상수 함수) \(2\pi\) \(\sqrt{2\pi}\)
\(\cos kx\) (\(k \geq 1\)) \(\pi\) \(\sqrt{\pi}\)
\(\sin kx\) (\(k \geq 1\)) \(\pi\) \(\sqrt{\pi}\)

\(\sin^2 kx\) 의 적분이 \(\pi\) 인 이유: \(\sin^2 kx = \frac{1}{2} - \frac{1}{2}\cos 2kx\) 이므로 \(\int_0^{2\pi} \sin^2 kx \, dx = \frac{1}{2} \cdot 2\pi - 0 = \pi\) 다.

4.3 정규직교 기저

길이로 나누면 정규직교(orthonormal) 기저가 된다.

\[ \frac{1}{\sqrt{2\pi}}, \quad \frac{\cos x}{\sqrt{\pi}}, \quad \frac{\sin x}{\sqrt{\pi}}, \quad \frac{\cos 2x}{\sqrt{\pi}}, \quad \frac{\sin 2x}{\sqrt{\pi}}, \quad \ldots \]

이것은 \(\mathbb{R}^n\) 의 정규직교 행렬 \(Q\) (\(Q^\top Q = I\))의 무한차원 버전이다. “무한 개의 열을 가진 직교 행렬”이라고 생각하면 된다. 그 역행렬은 전치이고, 직교성이 전체 급수를 각각의 한 항으로 환원시킨다.

4.4 왜 sin/cos인가 — 미분 연산자의 고유벡터

\(\sin kx\)\(\cos kx\) 가 특별한 이유는 이들이 이계 미분 연산자 \(-d^2/dx^2\) 의 고유함수(eigenvector)이기 때문이다.

\[ -\frac{d^2}{dx^2}(\sin kx) = k^2 \sin kx, \quad -\frac{d^2}{dx^2}(\cos kx) = k^2 \cos kx \]

고유값은 \(k^2\) 이다. 유한차원에서 대칭 행렬의 고유벡터가 직교한다는 스펙트럼 정리(Ch.6 §6.4)가, 무한차원에서 대칭 연산자의 고유함수가 직교한다는 것으로 확장된다. 물리학에서 진동하는 현(string)의 고유 모드가 \(\sin kx\) 인 것은 이 때문이다 — 경계 조건과 미분 방정식이 직교 기저를 결정한다.

5 푸리에 급수와 계수: 직교성이 일을 쉽게 만든다

5.1 급수 전개

\([0, 2\pi]\) 에서 주기적인 함수 \(f(x)\) 를 직교 기저로 분해한다.

\[ f(x) = a_0 + a_1 \cos x + b_1 \sin x + a_2 \cos 2x + b_2 \sin 2x + \cdots \]

\[ = a_0 + \sum_{k=1}^{\infty} (a_k \cos kx + b_k \sin kx) \]

이것이 푸리에 급수(Fourier series) 다. 유한차원에서 \(\mathbf{b} = c_1 \mathbf{v}_1 + \cdots + c_n \mathbf{v}_n\) 과 완전히 같은 구조이되, 기저가 무한 개다.

5.2 계수 계산: 내적으로

\(a_k\) 를 구하려면 양변에 \(\cos kx\) 를 곱하고 \([0, 2\pi]\) 에서 적분한다. 직교성 덕분에 오른쪽에서 \(\cos kx\) 항만 살아남는다.

\[ \int_0^{2\pi} f(x) \cos kx \, dx = a_k \int_0^{2\pi} \cos^2 kx \, dx = \pi a_k \]

따라서:

\[ a_k = \frac{1}{\pi} \int_0^{2\pi} f(x) \cos kx \, dx \quad (k \geq 1) \]

\[ b_k = \frac{1}{\pi} \int_0^{2\pi} f(x) \sin kx \, dx \quad (k \geq 1) \]

\(a_0\) 은 예외다. 상수 함수 1의 길이의 제곱이 \(2\pi\) 이므로:

\[ a_0 = \frac{1}{2\pi} \int_0^{2\pi} f(x) \, dx = \text{(함수의 평균값)} \]

이 공식들은 유한차원의 좌표 공식 \(c_k = \mathbf{v}_k^\top \mathbf{b} / \mathbf{v}_k^\top \mathbf{v}_k\) 의 정확한 무한차원 대응물이다.

  • 분자: 함수 \(f\) 와 기저 함수 \(\cos kx\) 의 내적 \(\int f(x) \cos kx \, dx\)
  • 분모: 기저 함수의 길이의 제곱 \(\int \cos^2 kx \, dx = \pi\)

직교성이 계산을 극적으로 단순화한다. 직교가 아닌 기저로 분해하려면 연립방정식(무한 개!)을 풀어야 하지만, 직교 기저에서는 각 계수를 독립적으로 내적 한 번으로 구한다. 이것이 Ch.4 §4.4의 Gram-Schmidt와 정규직교 기저가 중요한 근본적 이유다.

6 사각파 예제: 불연속 함수도 분해된다

6.1 푸리에 급수 계산

사각파(square wave) \(f(x)\) 를 다음과 같이 정의한다.

\[ f(x) = \begin{cases} +1 & 0 \leq x < \pi \\ -1 & \pi \leq x < 2\pi \end{cases} \]

이 함수는 불연속이다. 그런데도 푸리에 급수로 분해할 수 있을까? 된다.

\(f(x)\)홀함수(odd function)이다: \(f(-x) = -f(x)\). 홀함수의 푸리에 급수에는 \(\cos\) 항이 없다. 왜냐하면 \(\cos kx\) 는 짝함수이고, 홀함수와 짝함수의 내적(적분)은 0이기 때문이다.

\(b_k\) 를 계산한다.

\[ b_k = \frac{1}{\pi} \int_0^{2\pi} f(x) \sin kx \, dx = \frac{1}{\pi}\left[\int_0^{\pi} \sin kx \, dx - \int_{\pi}^{2\pi} \sin kx \, dx\right] \]

\(k\) 가 짝수이면 두 적분이 상쇄되어 \(b_k = 0\) 이다. \(k\) 가 홀수이면:

\[ b_k = \frac{4}{\pi k} \quad (k = 1, 3, 5, \ldots) \]

따라서 사각파의 푸리에 급수는:

\[ f(x) = \frac{4}{\pi}\left[\frac{\sin x}{1} + \frac{\sin 3x}{3} + \frac{\sin 5x}{5} + \frac{\sin 7x}{7} + \cdots\right] \]

홀수 사인만 등장한다. 이것은 “사각파 = 기본 진동 + 홀수 배음(odd harmonics)의 합”이라는 물리적 의미를 갖는다. 음향학에서 클라리넷 소리가 사각파에 가깝고 홀수 배음이 강한 이유가 바로 이것이다.

6.2 라이프니츠 급수: 직교성의 부산물

사각파의 푸리에 급수에 \(x = \pi/2\) 를 대입하면 놀라운 일이 벌어진다.

\(x = \pi/2\) 에서 \(\sin(\pi/2) = 1\), \(\sin(3\pi/2) = -1\), \(\sin(5\pi/2) = 1\), \(\sin(7\pi/2) = -1\), … 이고 \(f(\pi/2) = 1\) 이다.

\[ 1 = \frac{4}{\pi}\left(1 - \frac{1}{3} + \frac{1}{5} - \frac{1}{7} + \cdots\right) \]

\[ \frac{\pi}{4} = 1 - \frac{1}{3} + \frac{1}{5} - \frac{1}{7} + \cdots \]

이것이 유명한 라이프니츠 급수(Leibniz series) 다. 원주율 \(\pi\) 가 홀수의 역수를 번갈아 더하고 빼는 것으로 표현된다. 이 결과는 삼각함수의 직교성이 만들어낸 아름다운 부산물이다 — 순수하게 대수적인 사실(\(\pi\) 의 값)이 기하학적 직교성에서 나온다.

6.3 깁스 현상: 불연속점에서의 오버슈트

사각파의 푸리에 급수는 불연속점 \(x = 0, \pi\) 에서 중간값 0을 준다 — \(+1\) 에서 \(-1\) 로의 점프의 중간이다. 그런데 유한 개의 항만 합하면, 불연속점 근처에서 약 9%의 오버슈트(overshoot) 가 발생한다. 이것이 깁스 현상(Gibbs phenomenon)이다.

항의 개수를 \(N\) 으로 늘려도 오버슈트의 비율은 줄지 않고, 오버슈트가 일어나는 만 좁아진다. 즉 \(N \to \infty\) 에서 “뾰족한 돌출”이 사라지지 않고 불연속점으로 쫓겨갈 뿐이다. 이것은 유한차원에서는 볼 수 없는 무한차원 특유의 현상이다.

7 Parseval 정리: 함수의 길이 = 계수의 길이

7.1 정리 서술

정리: Parseval의 등식

\[ \|f\|^2 = \int_0^{2\pi} [f(x)]^2 \, dx = 2\pi a_0^2 + \pi \sum_{k=1}^{\infty} (a_k^2 + b_k^2) \]

7.2 왜 성립하는가 — 직교성

증명은 놀랍도록 짧다. \(f(x)\) 를 푸리에 급수로 대입하고 제곱하여 적분하면, 직교성 덕분에 교차항(예: \(\cos x \cdot \cos 2x\))의 적분이 모두 0이 된다. 제곱항만 남는다.

\[ \int_0^{2\pi} f^2 \, dx = a_0^2 \cdot 2\pi + a_1^2 \cdot \pi + b_1^2 \cdot \pi + a_2^2 \cdot \pi + \cdots \]

이것은 유한차원에서 정규직교 행렬 \(Q\) 에 대해 \(\|Q\mathbf{c}\| = \|\mathbf{c}\|\) 인 것의 정확한 무한차원 대응물이다.

7.3 직관적 의미

Parseval 정리는 “에너지 보존 법칙”이다.

  • 왼쪽 \(\|f\|^2\) 은 함수의 시간 영역(time domain) 에너지 — 함수를 시간(또는 공간)으로 본 것이다.
  • 오른쪽 \(\sum (a_k^2 + b_k^2)\)주파수 영역(frequency domain) 에너지 — 함수를 주파수 성분으로 분해한 것이다.

어떤 관점에서 보든 에너지의 총합은 같다. 이것은 물리학에서 기본적인 보존 법칙이며, 수학적으로는 함수 공간 \(L^2\) 와 좌표 공간 \(\ell^2\)등거리(isometric) 대응한다는 의미다.

7.4 사각파에 적용

사각파의 \(\|f\|^2 = \int_0^{2\pi} 1 \, dx = 2\pi\) 이다 (함수값이 \(\pm 1\) 이므로 제곱은 항상 1).

Parseval 정리를 적용하면 (\(a_0 = 0\), \(a_k = 0\), \(b_k = 4/(\pi k)\) for 홀수 \(k\)):

\[ 2\pi = \pi \sum_{k \text{ odd}} \left(\frac{4}{\pi k}\right)^2 = \frac{16}{\pi} \sum_{k \text{ odd}} \frac{1}{k^2} \]

정리하면:

\[ \sum_{k \text{ odd}} \frac{1}{k^2} = 1 + \frac{1}{9} + \frac{1}{25} + \frac{1}{49} + \cdots = \frac{\pi^2}{8} \]

이로부터 바젤 문제(Basel problem)의 해 \(\sum_{k=1}^{\infty} 1/k^2 = \pi^2/6\) 도 유도할 수 있다. 직교성이라는 하나의 원리에서 \(\pi\) 에 관한 심원한 등식들이 줄줄이 떨어진다.

8 왜 필요한가: 데이터 사이언스와 공학에서의 응용

분야 푸리에 급수와의 연결 구체적 예시
신호처리 시간 영역 신호를 주파수 성분으로 분해 음성 인식, 노이즈 필터링, 스펙트럼 분석
이미지 압축 DCT(Discrete Cosine Transform)는 푸리에의 사촌 JPEG 압축: 이미지를 cos 기저로 분해, 작은 계수를 버림
딥러닝 sin/cos 기반 위치 인코딩 Transformer의 positional encoding: \(PE(pos, 2i) = \sin(pos/10000^{2i/d})\)
PDE 풀이 열방정식, 파동방정식의 일반해 초기 조건을 푸리에 급수로 분해 \(\to\) 각 모드가 독립적으로 진화
시계열 분석 주기적 패턴 검출 매출 데이터에서 주간/월간/연간 주기를 주파수 성분으로 분리
양자역학 위치-운동량의 푸리에 쌍대성 파동함수의 운동량 표현 = 위치 표현의 푸리에 변환
Neural ODE / FNO 함수 공간에서의 학습 Fourier Neural Operator: 주파수 영역에서 커널을 학습하여 PDE를 풂
JPEG 압축과 푸리에의 연결

JPEG 압축은 본질적으로 “이미지에 대한 푸리에 분해”다. 8x8 블록의 이미지를 DCT로 변환하면 대부분의 에너지가 소수의 저주파 계수에 집중된다. 고주파 계수(디테일)를 버려도 눈으로 보기에 큰 차이가 없다 — Parseval 정리에 의해 버린 계수의 에너지 합이 작기 때문이다. 압축률과 화질의 트레이드오프는 “몇 개의 푸리에 계수를 유지할 것인가”의 문제다.

9 코드 예시

9.1 Step 1: Low-level 구현 (원리 이해)

import numpy as np

def fourier_coefficients(f_values, x_values, K):
    """
    수치적으로 푸리에 계수를 계산한다.
    직교성 원리를 직접 구현 — 각 계수는 함수와 기저의 내적/기저의 길이^2.

    f_values: f(x)의 값들 (1D array)
    x_values: x 좌표들 (1D array, [0, 2pi] 구간)
    K: 계산할 최대 주파수
    """
    dx = x_values[1] - x_values[0]  # 적분을 리만합으로 근사

    # a0 = (1/2pi) * integral of f(x) dx = 평균값
    a0 = np.sum(f_values) * dx / (2 * np.pi)

    a_k = []
    b_k = []
    for k in range(1, K + 1):
        # a_k = (1/pi) * integral of f(x) * cos(kx) dx  -- 내적 / 길이^2
        ak = np.sum(f_values * np.cos(k * x_values)) * dx / np.pi
        # b_k = (1/pi) * integral of f(x) * sin(kx) dx
        bk = np.sum(f_values * np.sin(k * x_values)) * dx / np.pi
        a_k.append(ak)
        b_k.append(bk)

    return a0, np.array(a_k), np.array(b_k)


def fourier_reconstruct(a0, a_k, b_k, x_values):
    """푸리에 계수로부터 함수를 복원한다."""
    result = np.full_like(x_values, a0, dtype=float)
    for k in range(len(a_k)):
        result += a_k[k] * np.cos((k + 1) * x_values)
        result += b_k[k] * np.sin((k + 1) * x_values)
    return result


# 사각파 정의
N = 10000
x = np.linspace(0, 2 * np.pi, N, endpoint=False)
f_square = np.where(x < np.pi, 1.0, -1.0)

# 푸리에 계수 계산
K = 10
a0, a_k, b_k = fourier_coefficients(f_square, x, K)

print(f"a0 = {a0:.6f}  (이론값: 0)")
print(f"\n코사인 계수 (모두 ~0이어야 함, 홀함수이므로):")
for k, ak in enumerate(a_k, 1):
    if abs(ak) > 1e-10:
        print(f"  a_{k} = {ak:.6f}")

print(f"\n사인 계수:")
for k, bk in enumerate(b_k, 1):
    theoretical = 4 / (np.pi * k) if k % 2 == 1 else 0
    print(f"  b_{k} = {bk:.6f}  (이론값: {theoretical:.6f})")

# Parseval 정리 검증
energy_time = np.sum(f_square**2) * (2 * np.pi / N)  # ||f||^2
energy_freq = 2 * np.pi * a0**2 + np.pi * (np.sum(a_k**2) + np.sum(b_k**2))

print(f"\n== Parseval 정리 검증 ==")
print(f"시간 영역 에너지: {energy_time:.4f}")
print(f"주파수 영역 에너지 (K={K}): {energy_freq:.4f}")
print(f"이론값: {2 * np.pi:.4f}")
# K를 키울수록 주파수 영역 에너지가 2*pi에 수렴한다

9.2 Step 2: NumPy/Matplotlib 실무 코드

import numpy as np
import matplotlib.pyplot as plt

# 사각파와 푸리에 근사 시각화
N_points = 1000
x = np.linspace(0, 2 * np.pi, N_points, endpoint=False)
f_square = np.where(x < np.pi, 1.0, -1.0)

fig, axes = plt.subplots(2, 2, figsize=(12, 8))

for idx, K in enumerate([1, 3, 10, 50]):
    ax = axes[idx // 2][idx % 2]

    # 해석적 푸리에 급수 (사각파: 홀수 사인만)
    approx = np.zeros_like(x)
    for k in range(1, K + 1):
        if k % 2 == 1:  # 홀수만
            approx += (4 / (np.pi * k)) * np.sin(k * x)

    ax.plot(x, f_square, 'k--', alpha=0.5, label='사각파')
    ax.plot(x, approx, 'b-', linewidth=1.5, label=f'{K}항 근사')
    ax.set_title(f'K = {K}', fontsize=12)
    ax.set_xlim(0, 2 * np.pi)
    ax.set_ylim(-1.5, 1.5)
    ax.legend()
    ax.grid(True, alpha=0.3)

plt.suptitle('사각파의 푸리에 급수 근사 (깁스 현상 관찰)', fontsize=14)
plt.tight_layout()
plt.savefig('fourier_gibbs.png', dpi=150)
plt.show()
# Parseval 정리: 에너지 수렴 시각화
K_max = 100
K_values = range(1, K_max + 1)
cumulative_energy = []

running = 0
for k in K_values:
    if k % 2 == 1:
        running += np.pi * (4 / (np.pi * k))**2
    cumulative_energy.append(running)

total_energy = 2 * np.pi  # ||f||^2

plt.figure(figsize=(8, 5))
plt.plot(K_values, cumulative_energy, 'b-', linewidth=2, label='주파수 영역 누적 에너지')
plt.axhline(y=total_energy, color='r', linestyle='--', label=f'시간 영역 에너지 = 2pi = {total_energy:.2f}')
plt.xlabel('주파수 성분 수 K')
plt.ylabel('에너지')
plt.title('Parseval 정리: 에너지 보존')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('parseval_convergence.png', dpi=150)
plt.show()

9.3 Step 3: FFT를 이용한 실무 코드

import numpy as np

# 실무에서는 적분 대신 FFT(Fast Fourier Transform)를 사용한다.
# FFT는 이산 푸리에 변환(DFT)을 O(N log N)으로 계산하는 알고리즘이다.

N = 1024
x = np.linspace(0, 2 * np.pi, N, endpoint=False)
f = np.where(x < np.pi, 1.0, -1.0)

# FFT 계산
F = np.fft.rfft(f)  # 실수 입력 -> 양의 주파수만

# FFT 결과에서 푸리에 계수 추출
a0_fft = F[0].real / N
a_k_fft = 2 * F[1:].real / N
b_k_fft = -2 * F[1:].imag / N

print("FFT로 구한 사인 계수 (처음 10개):")
for k in range(10):
    print(f"  b_{k+1} = {b_k_fft[k]:.6f}", end="")
    theoretical = 4 / (np.pi * (k + 1)) if (k + 1) % 2 == 1 else 0
    print(f"  (이론값: {theoretical:.6f})")

# Parseval 정리: FFT 버전
energy_time = np.sum(f**2) / N
energy_freq = np.sum(np.abs(F)**2) / N**2  # 정규화
print(f"\nParseval (FFT): 시간={energy_time:.4f}, 주파수={energy_freq:.4f}")

10 요약: 푸리에 급수가 말하는 것

핵심 아이디어 유한차원 대응물 무한차원 표현
직교 기저 \(Q^\top Q = I\) \(\int \sin jx \cos kx \, dx = 0\)
좌표 = 내적 \(c_k = \mathbf{v}_k^\top \mathbf{b} / \mathbf{v}_k^\top \mathbf{v}_k\) \(a_k = \frac{1}{\pi}\int f(x)\cos kx \, dx\)
길이 보존 \(\|\mathbf{b}\|^2 = \sum c_k^2 \|\mathbf{v}_k\|^2\) \(\|f\|^2 = 2\pi a_0^2 + \pi\sum(a_k^2 + b_k^2)\)
분해의 유일성 기저가 공간을 span 함수 공간 \(L^2\) 의 완비 기저

푸리에 급수의 모든 공식은 Ch.4의 직교성과 정사영에서 나온다. 바뀐 것은 합이 적분이 된 것뿐이다. 함수해석학(functional analysis)의 출발점이 바로 이 관찰이다 — 선형대수의 유한차원 정리들이 적절한 조건(완비성, 가분성) 아래서 무한차원에서도 살아남는다는 것.

11 관련 주제

선행 지식

후속 주제

다른 카테고리 연결

Subscribe

Enjoy this blog? Get notified of new posts by email: