Função que espalha entrada


14

Gostaria de saber se existe uma função de números de n bits para números de n bits que possui as seguintes características:f

  • f deve ser bijetivo
  • Ambos e deve ser calculável rápido bastantef - 1ff1
  • f deve retornar um número que não tem correlação significativa com sua entrada.

A lógica é esta:

Eu quero escrever um programa que opera com dados. Algumas informações dos dados são armazenadas em uma árvore de pesquisa binária em que a chave de pesquisa é um símbolo de um alfabeto. Com o tempo, adiciono mais símbolos ao alfabeto. Novos símbolos simplesmente obtêm o próximo número gratuito disponível. Portanto, a árvore sempre terá um pequeno viés para chaves menores, o que causa mais reequilíbrio do que eu acho que deveria ser necessário.

Minha idéia é alterar os números dos símbolos com f modo que eles estejam amplamente espalhados por todo o intervalo de . Como os números dos símbolos são importantes apenas durante a entrada e a saída, o que ocorre apenas uma vez, a aplicação dessa função não deve ser muito cara.[0,2641]

Pensei em uma iteração do gerador de números aleatórios Xorshift, mas realmente não sei como desfazê-lo, embora teoricamente seja possível.

Alguém conhece essa função?
isso é uma boa ideia?


1
Eu não sou um especialista, mas talvez você pode usar uma permutação pseudorandom (ver, por exemplo, a cifra de Feistel )
Vor

Se você está essencialmente computando uma função hash, por que não usar hash?
vonbrand

@vonbrand Hashing não é reversível. Veja o requisito número 2.
FUZxxl

Por que isso tem que ser reversível? O que há de errado em torná-lo reversível pela pesquisa?
vonbrand

1
Você pode armazenar (f (x), x) como chaves.
precisa saber é o seguinte

Respostas:


6

Você pode usar o hash Fibonacci ,

.hF(k)=k512k512

Para , você obtém n números distintos por pares (aproximadamente) espalhados igualmente em [ 0 , 1 ] . Ao escalar para [ 1 .. M ] e arredondar (para baixo), você obtém números uniformemente distribuídos nesse intervalo.k=1,,nn[0,1][1..M]

Por exemplo, estes são redimensionados para [ 0..10000 ] (sequência original esquerda, classificação à direita):hF(1),,hF(200)[0..10000]

insira a descrição da imagem aqui

Esta é uma instância do que Knuth chama de hash multiplicativo . Para o tamanho das palavras do computador, A um número inteiro relativamente primo w e M o número de endereços necessários, usamoswAwM

h(k)=M((kAw)mod1)

como função de hash. O exemplo acima é apresentado com (certifique-se de poder computá-lo com precisão suficiente). Embora isso também funcione com qualquer outro número irracional além de , é um dos dois únicos números que leva aos números "mais uniformemente distribuídos". ϕ-1A/w=ϕ1=512ϕ1

Encontre mais em The Art of Computer Programming , Volume 3, de Donald Knuth (capítulo 6.4 da página 513 na segunda edição). Em particular, você descobrirá por que os números resultantes são distintos entre pares (pelo menos se ) e como calcular a função inversa se você usar e naturais em vez de .A w ϕ - 1nMAwϕ1


1
Como calcular eficiência? f1
precisa saber é

1
@rafrafl Espero que minha edição atenda um pouco à sua preocupação. Está claro, no entanto, que essas técnicas de hash não são nem particularmente projetadas para serem invertíveis com eficiência.
Raphael

Sim, eu vou votar, no entanto, eu não recomendaria como a resposta aceita.
Frafl

1

Para entradas de bits, esta função funciona:k

hash(n)=(nmod2k2)2k2+ndiv2k2

Isso é reversível, pois e possui pares não sequenciais , em que . Cuidado que saída e entrada podem estar correlacionadas, especialmente se sua entrada estiver em .{ n , m } , n < m h a s h ( m ) < h a s h ( n ) { 1 , , 2 khash(hash(n))=n{n,m},n<mhash(m)<hash(n){1,,2k21}

Ref: Função hash reversível


Parece simples e agradável. Vou testar esse.
FUZxxl

1
1. Dependendo da entrada, pode produzir correlação pesada (até para ρ de Spearman ) 2. Isso é para 32 bits, não para 64 bits 3. Você poderia escrever isso de uma maneira independente da linguagem? 1ρ
precisa saber é

está bem claro! para 64 bits (0x00000000FFFFFFFF) e você deve deslocar (<<) 32 bits. Esta função é simples, prática e rápida o suficiente na prática.
Reza

1
Mas por que você não usa uma permutação dos bits, que não mapeia todo para 2 32 x ? Como mencionado acima, isso viola claramente a condição de correlação exigida pelo OP. x{1,,2321}232x
frafl 6/03/2013
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.