【问题标题】:Minimal perfect hashing of integers in base two range基数为二的整数的最小完美散列
【发布时间】:2016-09-22 00:06:58
【问题描述】:

我正在使用一个简单的散列函数,该函数将取一个基数为 2 的范围内的整数,并(随机)散列到该范围内的另一个整数而不会发生冲突。这将用于构造排列,最好是从种子值。所以仅仅偏移整数和调制是行不通的。有人知道用 C 编写的一个不错的选择吗?

谢谢, 乔什

【问题讨论】:

  • 嗨!我记得一些涉及对称群的事情。我明天可以检查一下,但如果你想在此期间检查一下,也许你会在这里找到一些东西:books.google.de/…
  • 谢谢@fr_andres,我去看看。

标签: c hash integer range perfect


【解决方案1】:

我在 Andrew Kensler 的论文 Correlated Multi-Jittered Sampling 中找到了一个很好的解决方案。这里使用仅由可逆运算符组成的混合函数来构造排列。这保证了在 2 的幂范围内不会发生冲突。

该函数是通过使用爬山程序迭代地找到的,该程序根据其雪崩特性评估每个候选者。此外,Kensler 使用称为循环行走的技术对哈希进行概括,以允许不是 2 的幂的范围。

由于这一点,结果的质量以及轻松打乱排列的能力,所提出的函数是原始问题的一个很好的解决方案。有关可逆运算符和生成质量混合函数的更多详细信息,请参阅 Bret Mulvey 关于哈希函数 here 的文章。

【讨论】:

  • 不错!我会检查它
【解决方案2】:

这可能会有所帮助(有关更通用的方法,请参见底部):multiplicative cyclic groups 允许您选择 k“种子”值、n“最大值”值,并从零开始排列自然数以非常有效的方式到 n-1(k 可以在 Z 中,但最好是两个自然数)。如果你想要一个排列,唯一的问题是 n 必须是一个素数,而且我不确定所有排列是否均匀分布在种子空间周围(关于 cryptography 的一些知识在这里会有很大帮助)。

主要操作将是这样的,在伪代码中:

for i in range(0, n){ i:= (i*k)(mod n);}

这里有一个 C 语言的工作玩具程序:

#include <stdio.h>

int main(void)
{
  // take a prime number (from https://primes.utm.edu/lists/2small/0bit.html)
  //int n = (int)pow(2,13)-1;
  // for the sake of test, let's take a little one:
  int n = 23;
  // take a random integer seed:
  int k = 1234;
  printf("permutation of numbers from 0 below %d with seed %d:\n", n, k);
  for (int i=0; i<n; i++){
    printf("%d ", ((i*k)%n));
  }
  printf("\n");
  return 0;
}

返回:

permutation of numbers from 0 below 23 with seed 1234:
0 15 7 22 14 6 21 13 5 20 12 4 19 11 3 18 10 2 17 9 1 16 8 

这并不完全是您想要的,但通过一些调整它可以正常工作......除非我们谈论的是高端安全性的东西。可能最直接的解决方案是选择接近 2 次方的素数,并进行一些调整? https://primes.utm.edu/lists/2small/

如果有帮助请告诉我!

编辑我忍不住在我的emacs上直接测试,所以这里是后代的功能:

(defun permute (n seed)
  "prints a permutation of the set of numbers between 0 and n-1, 
   provided n is prime"
  (let ((permuted (loop for i below n collect (% (* i seed) n))))
    (print permuted)
    ;(print (sort permuted '<)) ; debug print
    ))

(test 23  1234) ; returns (0 15 7 22 14 6 21 13 5 20 12 4 19 11 3 18 10 2 17 9 1 16 8)

编辑 2 实际上,正如Bézout's theorem 中所述,kn 互为质数就足够了。所以从技术上讲,如果你确保的话,你可以为n 拥有任意的自然值。一种简单但有限的方法是从素数列表中随机选择k。一个可能更好的解决方案是为每个给定的n 计算其相对素数,并从中选择(声明:8 和 9 都不是素数,但它们互为素数,因为 9(mod 8)= 1)。没有比这更“完整”的了,但我仍然不知道这种方法是如何分布排列的。

【讨论】:

  • 例如,如果你不希望0映射到0,你可以在所有结果中添加任意随机整数,然后再次计算模n...这样的调整
  • 感谢您查找@fr_andres,尽管有限制,这看起来是一个很好的解决方案。我将它用作(t,s)序列中间隔的排列,并且 2^7 是一个合理的大小。
  • 酷! :) 正如我所说,有一些肮脏的解决方法,所以让我知道它是否足够......如果你能分享你的解决方案,无论如何都会很棒。干杯
  • 是的,我会分享出现的任何其他解决方案,并会留意更普遍的东西。谢谢
  • 我相信如果你的k(种子)是素数,你的n可以是abritrary。但是这样排列空间显然会更小......
猜你喜欢
  • 1970-01-01
  • 2017-12-23
  • 1970-01-01
  • 1970-01-01
  • 2010-10-19
  • 1970-01-01
  • 1970-01-01
  • 2021-12-07
  • 2010-11-11
相关资源
最近更新 更多