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 - 1ff−1
  • 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,264−1]

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)=k⋅5−12−⌊k⋅5−12⌋

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((k⋅Aw)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=5−12ϕ−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 ϕ - 1n≪MAwϕ−1


1
Como calcular eficiência? f−1
— 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)=(nmod2⌈k2⌉)⋅2⌈k2⌉+ndiv2⌈k2⌉

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,…,2⌈k2⌉−1}

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,…,232−1}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.