Multiplicação de número inteiro quando um número inteiro é fixo

35

Seja um número inteiro positivo fixo de tamanho bits.nAn

É permitido pré-processar esse número inteiro, conforme apropriado.

Dado outro número inteiro positivo de tamanho bits, qual é a complexidade da multiplicação ?m A BBmAB

Observe que já temos os algoritmos . A questão aqui é se podemos tomar \ epsilon = 0 por algo mais inteligente? ϵ = 0(max(n,m))1+ϵϵ=0

T ....
fonte
6
Dado A , basta construir uma tabela de pesquisa com 2n entradas. (Obviamente, isso não é o que você queria, mas eu acho que você deve fazer suas necessidades mais específicas ...)
Jukka Suomela
9
Penso que a questão faz todo o sentido no modelo de circuito booleano padrão.
Noam
4
Você poderia resumir os limites superiores e inferiores óbvios e os melhores resultados que conhece? Isso mostra que você se preocupa com o problema e que você pensou sobre isso, além de dar a todos os outros mais incentivo para pensar sobre o seu problema.
precisa
4
Penso que o autor da pergunta implica implicitamente que a parte pré-processada deve ocupar apenas nO(1) espaço. (A mult matriz-vector tem essa propriedade.)
Ryan Williams
Eu gostaria de saber exatamente o que você gostaria; Eu sinto que eu poderia passar por infinitos casos sobre isso. Esta é a minha primeira resposta, por isso estou especialmente feliz em tentar fornecer o máximo de informações possível. Se desejar, envie um e-mail para [email protected], e ficarei feliz em trabalhar com você muito mais.
quer

Respostas:

20

Embora nem sempre seja o algoritmo mais eficiente, esta questão tem uma relação muito próxima com cadeias de adição; qualquer algoritmo para calcular rapidamente por cadeias de adição se traduz em um algoritmo para calcular por adição repetida (cada adição, obviamente, é uma operação ). Por outro lado, um algoritmo rápido para calcular para qualquer leva a um algoritmo rápido para calcular , mas é claro que esse algoritmo não precisa necessariamente ter a forma de uma cadeia de adição; Ainda assim, parece um excelente lugar para começar. Dê uma olhada em http://en.wikipedia.org/wiki/Addition_chain ou confira o vol. 2 def ( B ) = A B O ( n ) A B B AAf(B)=ABO(n)ABBAThe Art Of Computer Programming para mais detalhes.

Steven Stadnicki
fonte
17

Para expandir a idéia de Steven Stadnicki, podemos rapidamente construir um algoritmo ingênuo que se sai melhor do que a multiplicação de matrizes usando a Transformada Discreta de Fourier.

Contamos o número de uns em . Se menos da metade dos bits forem um, construímos uma lista vinculada de suas posições. Para multiplicar, simplesmente deslocamos para cada posição da lista (multiplicando pelo bit representado) e adicionamos os resultados.BAB

Se mais da metade dos bits são um, fazemos o mesmo que acima, mas usamos os zeros para preencher a lista de posições. A idéia é que subtrairemos essa soma da soma que seria obtida multiplicando por todas. Para obter a soma de todos, alteramos pelo número de bits em e subtraímos disso. Em seguida, podemos subtrair nossa soma obtida da lista vinculada.A BBAB

Podemos chamar isso de ingênuo algoritmo de lista vinculada. Seu tempo de execução é no pior caso, mas no caso médio, que é mais rápido que o DFT para pequenos.O ( | B | O(n2)O(|B||A|2π)|A|

Para usar a idéia de listas de maneira ideal, usamos dividir e conquistar. Dividimos ao meio e localizamos os tamanhos das listas associadas usando o algoritmo ingênuo. Se eles são maiores que 5, chamamos o algoritmo ingênuo novamente em metades maiores que 5 até conseguirmos cortar todas as metades para menos de cinco. (Isso ocorre porque podemos reduzir isso para 4 subtrações)A

Ainda melhor ainda, melhoramos nosso algoritmo de dividir e conquistar. Repetimos todas as combinações possíveis de ramificação, escolhendo avidamente a melhor. Esse pré-processamento leva aproximadamente o mesmo tempo que a multiplicação real.

Se nos for permitida liberdade infinita com o pré-processamento, resolveremos o algoritmo otimizado de dividir e conquistar para todos os ramos da melhor maneira possível. Isso leva tempo na pior das hipóteses, mas deve ser ótimo pelos métodos da cadeia de adição.O(2|A|)

Estou trabalhando no cálculo de valores mais exatos para os algoritmos acima.

Matt Groff
fonte
Oi Matt: O que ée? | B ||A||B|
T ....
A A n | Um | n | B | n A B|A|é o tamanho de , basicamente o número de elementos na . Isso é equivalente ao seu , ou seja, . O mesmo para. No entanto, esta fórmula ainda se mantém quando é diferente de e . AAn|A|n|B|nAB
quer
17

O artigo chamado Multiplicação por uma constante é sublinear ( PDF ) fornece um algoritmo para operações de deslocamento / adição , em que é o tamanho da constante .nO(nlogn)n

Essencialmente, ele funciona procurando os bits na constante, alterando e adicionando o número a ser multiplicado apenas para os bits na constante (como multiplicação longa para binário, onde um bit no número inferior a ser multiplicado significa a parte superior não é deslocado e adicionado, enquanto um bit significa a parte superior é deslocada e adicionado). No entanto, isso ainda é , porque pode haver bits na constante.1 0 1 O ( n ) O ( n ) 11101O(n)O(n) 1

O artigo então fala sobre a alteração da representação numérica da constante no sistema de números de base dupla, onde aparentemente os bits não- são mais escassos, se a conversão for feita corretamente (é um sistema numérico muito redundante). Eles calculam o quão escasso é; o número de bits diferentes de zero é limitado a menos que , portanto, há um número sublinear de adições necessárias. No entanto, ainda são operações reais , devido ao custo de cada adição (onde é o tamanho de a constante e é o tamanho do outro número).O ( n ) O ( n m0O(n)O(m)nmO(nmlogn)O(m)nm

Portanto, para responder sua pergunta, sim, há um resultado semelhante à multiplicação de vetores matriciais, pois você obtém um speedup se for constante; mas é claro que essa aceleração é apenas sobre multiplicação longa ingênua e existem algoritmos de multiplicação que são muito melhores que você pode obter esse algoritmo.O ( n 2lognO(n2logn)

Realz Slaw
fonte
@ Jas, que é minha especialidade: D.
Realz Slaw
3
Isso apareceu no ARITH 2007 como dx.doi.org/10.1109/ARITH.2007.24 (para ser completo).
András Salamon 15/10
10

Conforme sugerido por Matt Groff, você pode estar interessado em procurar inspiração na comunidade de praticantes (ou se na sua situação estiver dentro da largura de bits de uma CPU atual). De fato, o problema da multiplicação de números inteiros por uma constante foi considerado por muitos escritores de compiladores e projetistas de circuitos, embora eles geralmente estejam interessados ​​em "multiplicadores sem multiplicadores" (multiplique usando shift, add e subtrair). Uma das primeiras referências que conheço é (eu aprendi isso na seção 8.4 do Hacker's Delight).n

Bernstein, R. (1986), Multiplicação por constantes inteiras. Software: Practice and Experience, 16: 641–652. doi: 10.1002 / spe.4380160704

Um trabalho mais moderno de Vincent Lefèvre pode ser encontrado aqui (não deixe de ver os trabalhos de acompanhamento dele), e ele também observa um projeto da CMU sobre a síntese eficiente de circuitos (veja as referências ali). O último projeto ainda considera a multiplicação simultânea por um conjunto de constantes.

PS: Convido você a mudar seu nome de usuário para algo reconhecível.

Maverick Woo
fonte
9

Não tenho certeza se isso é diretamente relevante para a questão, mas o seguinte resultado elementar pode ser interessante. Dado um número natural fixo , a operação pode ser realizada por um autômato seqüencial, desde que seja escrito em notação binária invertida (ou seja, Menos Pouco Significativo Primeiro). O número de estados do autômato é onde é a maior potência de divide . Por exemplo, a operação é realizada pelo seguinte autômato. n k n n k / 2 r 2 r 2 k n 6 nknknnk/2r2r2kn6ninsira a descrição da imagem aqui

Por exemplo, e . Assim, no binário reverso, é escrito como e (má escolha, eu sei ...) como . O processamento da entrada neste autômato fornece o caminho 185=1+8+16+32+1286×185=1110=2+4+16+64+10241851001110111100110101000110011101 01101010001

0011101000011110211200110201
que fornece a saída correta . O tipo de autômato seqüencial que estou usando aqui foi chamado subsequencial por Schützenberger: como você pode ver, existe um prefixo inicial (em verde) e uma função de saída do terminal01101010001(também em verde). Para mais detalhes de como esta máquina seqüencial pode ser computada de forma sistemática, consulte este link .
J.-E. PIN
fonte
Você poderia elaborar seu comentário?
J.-E.
> 2k é primo . >2
T ....
A construção de um autômato seqüencial que realiza a operação pode ser feita para qualquer . No entanto, calcular esse autômato pode ser mais fácil para o prime. k knknkk
J.-E.
k2r é exponencial.
T ....
nk é uma constante fixa, não relacionada a . n
J.-E.