تبدیل فوریهی سریع (FFT)
مقدار چندجملهای را در n ریشهی واحد با تقسیم و حل در O(n log n) حساب میکند (و برعکس، با FFT وارون)؛ پایهی ضرب سریع چندجملهایها.
چندجملهای A(x) = a_0 + a_1·x + … + a_{n−1}·x^{n−1} را میخواهیم در n نقطه حساب کنیم. اگر نقطهها ریشههای nام واحد ω^0, ω^1, …, ω^{n−1} (با ω = e^{2πi/n}) باشند، ترفندی ممکن است:
- زمان:
O(n log n) - حافظه:
O(n log n) (recursive) - CLRS، بخش ۳۰.۲
A(x) = 1 + 2x + 3x² + 4x³ در چهار ریشهی چهارم واحد (1، i، −1، −i): ۱۰، −2−2i، −2، −2+2i.
import cmathdef transform(coeffs, inverse):a = coeffs[0]n = len(a)if n & (n - 1) != 0:return Noney = fft(a, inverse)if inverse:y = [v / n for v in y]rows = [(k, show(v)) for k, v in enumerate(y)]return [show(v) for v in y]def fft(a, inverse):n = len(a)if n == 1:return [complex(a[0])]sign = -1 if inverse else 1w_n = cmath.exp(sign * 2j * cmath.pi / n) # the principal n-th root of unityeven = fft(a[0::2], inverse)odd = fft(a[1::2], inverse)y = [0] * nw = 1for k in range(n // 2):t = w * odd[k]y[k] = even[k] + ty[k + n // 2] = even[k] - tw = w * w_nreturn ydef show(z):# Rounded for reading, e.g. "2-1.414i".re, im = round(z.real, 3) + 0.0, round(z.imag, 3) + 0.0return f"{re:g}" if im == 0 else f"{re:g}{im:+g}i"
شروع اجرا
جدول هنوز خالی است.
درخت فراخوانیهای بازگشتی
نارنجی پر = فراخوانی در حال اجرا · حاشیهی نارنجی = هنوز روی پشته · خاکستری = تمام شده
متغیرهای محلی
نارنجی = در همین گام عوض شد
coeffs list
Call stack
- transform()خط 4
توضیح
ایده
چندجملهای A(x) = a_0 + a_1·x + … + a_{n−1}·x^{n−1} را میخواهیم در n نقطه حساب کنیم. اگر نقطهها ریشههای nام واحد ω^0, ω^1, …, ω^{n−1} (با ω = e^{2πi/n}) باشند، ترفندی ممکن است:
A(x) = A_زوج(x²) + x · A_فرد(x²)
و مربع ریشههای nام همان ریشههای (n/2)اماند. پس دو مسئلهی نیماندازه حل میکنیم و با پروانهها ترکیب میکنیم:
y[k] = y⁰[k] + ω^k·y¹[k] y[k + n/2] = y⁰[k] − ω^k·y¹[k]
T(n) = 2T(n/2) + O(n) = O(n log n)، در برابر O(n²) برای حساب جداگانهی n مقدار.
FFT وارون
برگشت از مقدارها به ضریبها همان FFT است با ω⁻¹ بهجای ω و تقسیم بر n (پارامتر inverse = 1).
در trace به چه چیزی نگاه کنی
- درخت فراخوانی دودویی است (زوج و فرد)؛ جدول آخر مقدارهای گردشده است.