不存在“k 向独立散列函数”之类的东西。但是,有 k 方向独立的函数族。
提醒一下,如果从族中随机挑选 h 并且任意挑选 x_1 .. x_k 和 y_1 .. y_k ,则函数族是 k 向独立的,“对于所有 i,h(x_i) = y_i " 是 Y^-k,其中 Y 是从中选择 y_i 的共域的大小。
已知有一些函数族对于像 2、3、4 和 5 这样的小 k 是 k 方向独立的。对于任意 k,您可能需要使用多项式哈希。请注意,它有两种变体,其中一种甚至不是 2 独立的,因此在实现它时要小心。
多项式散列族可以使用 k 常数 a_0 到 a_{k-1} 从字段 F 散列到自身,并由 a_i x^i 之和定义,其中 x 是您要散列的键。通过让 F 为以素数 p 为模的整数,可以在您的计算机上实现域算术。这可能不方便,因为域和范围通常更好uint32_t
之类的。在这种情况下,您可以使用字段 F_{2^32},您可以使用 Z_2 上的多项式乘法,然后除以该字段中的不可约多项式。否则,您可以在 Z_p 中操作,其中 p 大于 2^32(或 64)并取多项式模 2^32 的结果,我认为。这将几乎是k-wise独立的,但有时这足以让分析通过。重新分析 KNW 算法以改变其哈希族并不容易。
要生成 k-wise 独立族的成员,请使用您最喜欢的随机数生成器随机选择函数。在多项式哈希的情况下,这意味着选择a
上面提到的 s。/dev/random
应该足够了。
您指向的论文“An Optimal Algorithm for the Distinct Elements Problem”是一篇不错的论文,已被多次引用。然而,它并不容易实现,而且它可能比 HyperLogLog 更慢甚至占用更多空间,这是由于 big-O 符号中的隐藏常量。许多论文已经注意到该算法的复杂性,甚至称其与 HyperLogLog 相比是不可行的。如果您想为不同元素的数量实现估计器,您可以从早期的算法开始。如果您的目标是教育,那么那里有很多复杂性。如果您的目标是实用性,那么您也希望远离 KNW,因为仅仅为了让 HyperLogLog 不太实用可能需要做很多工作。
作为另一条建议,如果您想了解和理解此算法或其他使用散列的随机算法,您可能应该忽略“仅使用 Murmur 散列”或“从 xxhash 中选择 k 值”的建议。Murmur/xx 在实践中可能没问题,但它们不是 k-wise 独立的族,并且此页面上的一些建议甚至在语义上都不是格式正确的。例如,“如果你需要 k 个不同的散列,只需重复使用相同的算法 k 次,使用 k 个不同的种子”与 k-wise 独立族无关。对于您要实现的此算法,您最终将应用散列函数任意次数。你不需要“需要 k 个不同的哈希”,你需要n通过首先从与 k 无关的散列系列中随机选取,然后将所选函数应用于作为此类算法输入的流键,生成不同的散列值。