分配数字的模数用法示例
由于要求每个字符串限制在 0 到 5 或 1 到 6 之间的数字,并且数据集不断变化/不完整,因此不可能达到预期的最终结果。假设我们取 6 个字符串,我们将对它们进行 crc,然后进行模数 6 并显示结果。输入:
Array
(
[0] => string1
[1] => string2
[2] => string3
[3] => string4
[4] => string5
[5] => string6
)
(crc32
使用sprintf('%u', crc32('string'))
:
Array
(
[0] => 742935113
[1] => 3040943091
[2] => 3259378533
[3] => 1545780934
[4] => 723881552
[5] => 2989285354
)
结果crc32 % 6
:
Array
(
[0] => 5
[1] => 1
[2] => 1
[3] => 4
[4] => 2
[5] => 1
)
如您所见,“string2”、“string3”和“string6”都与桶发生冲突,导致它们被分配一个“1”,通过碰撞检测,一个简单的+1
直到找到一个空桶将用于这个例子。所以我们最终得到了我们的bucket
数组:
Array
(
[0] => string6
[1] => string2
[2] => string3
[3] => string5
[4] => string4
[5] => string1
)
下一次,假设我们摆脱[1] => string2
了原始输入,那么我们的 6 个结果数组将如下所示:
Array
(
[0] =>
[1] => string3
[2] => string5
[3] => string6
[4] => string4
[5] => string1
)
这显示了当数据集不完整且包含少量键时会发生什么,分配的数字对于某些人来说是截然不同的。
问题是load
. 这个负载是 100%,因为有 6 个可能的文本,并且只有 6 个buckets
。创建哈希表时,您希望负载接近 0,对于 6 个条目的 50% 负载,您需要 12 个可用存储桶。
记住
在 PHP 中使用 amodulus
时,您还必须记住最大整数大小,因为用于模运算的任何值都将转换为整数:
模数的操作数在处理之前被转换为整数(通过去除小数部分)。
根据您的系统,这将是 32 位或 64 位。一个无符号的 crc32 将超过 32 位系统上的最大上限并返回 int 上限,这意味着一半的数字将在同一个桶中结束(统计上),这正是我们之前一半的值在桶 '1 中结束时发生的情况'。
我们能做些什么?
好吧,问题是我们可以选择的数字范围。根据分配不同字符串数字的所需应用程序,我们可以使用实crc32
数,因为对于小数据集,结果中的冲突数量将是最小的 - 但是,如果我们需要输入文本的连续数字集(或在如所描述的一个小范围),没有解决方案可以允许部分数据集,同时在每次运行中保持分配的数字不变。由于每次运行脚本时输入字符串的顺序都是随机的,因此绝对没有办法每次都保持结果整数相同,因为如果在每次运行之间的不同时间处理冲突,它们的顺序可能会颠倒。
如果目的是标记文件或访问某些内容的方式,请使用更大的散列,不要mod
让它适合它的大小。