Você pode entender os computadores modernos simplesmente como grandes e poderosas calculadoras. A capacidade de memória e a velocidade com que estas máquinas realizam cálculos gigantescos é realmente incrível. Por trás disso tudo, existe muita matemática e engenharia. Se você já procurou entender como que um computador realiza seus cálculos, deve ter notado que existem ideias simples e geniais por trás de seus algoritmos.
Mesmo assim, o advento da criptografia RSA (só para dar um exemplo), exigiu que pudéssemos trabalhar com números inteiros muito grandes. Muito grandes mesmo! Para ter uma ideia, dê uma olhada na lista dos maiores primos de Mersenne conhecidos atualmente e você terá uma noção da ordem de grandeza destes números. Estamos falando de milhões de dígitos. A coisa é tão feia que, para esrever um programa que realize operações com estes números, é preciso utilizar uma biblioteca especial (existem várias bibliotecas com este propósito).
Mas o problema é mais em baixo. Multiplicar dois números é um processo extremamente custoso para um computador! Acredite, se você utilizar um algoritmo comum para multiplicar dois números com a ordem de grandeza mencionada anteriormente, terá que esperar sentado durante um bom tempo. Vamos entender mais ou menos o porquê.
Sejam
e
dois inteiros de
dígitos, representados na base
(usualmente, num computador,
). De forma geral, o produto de
por
é dado por

Assim, para computar o produto
temos de realizar cerca de
(isto é
) multiplicações entre os coeficientes da representação de
e
na base
e depois somá-las da forma adequada. Assim, efetuar o produto "usual'' entre dois inteiros num computador se torna um processo extremamente lento quando
é grande. Para contornar esta situação vamos apresentar a matemática por trás de um algoritmo para multiplicar inteiros cuja complexidade é da ordem de
. Existem outros algoritmos, mas este é um dos melhores.
Para compreender o que segue você precisará saber (se você não sabe, o Google sabe, use-o!):
pontos em
com abscissas distintas, só existe um único polinômio
de grau
tal que o gráfico
passa por estes pontos.
Demonstração. Expresse os
pontos como solução de um sistema linear onde as incógnitas são os coeficientes do polinômio. A matriz deste sistema será uma Matriz de Vandermonde invertível. 
Em outras palavras, dados
, o lema acima nos diz que, se conhecemos
com
, para um polinômio
de grau
, então, de alguma forma, conhecemos os coeficientes de
Resta saber que pontos escolher. Esta é a ideia central da Transformada Discreta de Fourier (FFT).
Seja
,
. Definimos a matriz
por
é uma matriz complexa,
denota a transposta conjugada de
(isto é, a matriz adjunta).
Lema. A matriz complexa
como definida acima é uma matriz ortogonal. Além disso,
.
Demonstração. Primeiramente, note que

Assim, para computar o produto
Para compreender o que segue você precisará saber (se você não sabe, o Google sabe, use-o!):
- Álgebra Linear. Por exemplo, você deve saber o que é uma Matriz de Vandermonde, ortogonalidade e produto interno de vetores com entradas em
.
- Raízes da unidade.
- Complexidade de algoritmos (pouca coisa, basicamente só saber o que é Big O).
Demonstração. Expresse os
Em outras palavras, dados
Seja
Lema. A matriz complexa
Demonstração. Primeiramente, note que
Denote a coluna
pois
A multiplicação de inteiros pelo FFT consiste em escolher uma base
para
A priori faremos
Antes de exibirmos a fatoração, façamos algumas definições. Para
Por exemplo, para
Se
Feito isto, temos o grandioso
Teorema. Seja
onde
Demonstração. Seja
Multiplicando
Agora, se
Por fim, se
Observação 1. Talvez você tenha notado que, para a demonstração deste teorema, não precisamos do fato de
Observação 2. Para sentir como funciona a coisa, tente fazer um exemplo para
Em princício, para multiplicar
multiplicações, pois não precisamos contar a matriz de permutação, nem as matrizes identidade, e
Teorema. Nas condições do teorema acima, o número de multiplicações realizadas é
Demonstração. Na realidade, após realizar o processo
- [1ª interação]
- [2ª interação]
- [3ª interação]
- ...
Opa, algo está errado, não chegamos ao que queríamos! Mas a conta está certa; o fato é que, depois de realizarmos
O próximo problema seria achar a tranformada inversa, ou seja, obter os coeficientes do polinômio resultante da multiplicação. Em geral, inverter uma matriz é um processo custoso, mas inverter
Isto é tudo. A Transformada Discreta de Fourier tem inúmeras outras aplicações que, por hora, fogem do propósito deste post. Se você se interessou e quer saber um pouco mais sobre o assunto, seguem alguns links (todos em inglês): Video Aula sobre FFT de Gilbert Strang, Discrete Fourier Transform, Fast Fourier Transform, Livro online sobre Transformada Discreta de Fourier.
Referências:
- "Introduction to Linear Algebra'', Gilbert Strang.
- "Primos de Mersenne (e outros primos muito grandes)'', Carlos Gustavo T.A. Moreira e Nicolau C. Saldanha.
6 comentários:
Post legal =P
Sempre que eu multiplico inteiros de cabeça eu uso a FFT (ou não) xD
Eu gostei deste artigo já tinha visto a coisa antes mas este aí está bem explicado.
correção: deveria ter usado "este aqui" ou "esse aí" o que eu escrevi antes foi tenso... que se dane!
Espetacular sua explicação.
Olá. Parabéns pela explicação. No entanto, ainda me resta uma dúvida. Quando trabalhamos com softwares tipo MATLAB ou SciLab, ao calcularmos a fft, multiplicamos por um valor 2/N, onde N é o número de amostras para que o resultado das amplitudes sejam verdadeiros. Pela demonstração acima, os valores são multiplicados por Nlog(N). Então, o resultado não deveria ser divido por este valor? Poderia me ajudar a entender? Obrigado.
Muito interessante! Principalmente porquê quero especializar-me em Processamento de Sinais e Robótica. :)
Postar um comentário