【问题标题】:Hash sequential 64 bit number uniformly into 8 bits?将连续的 64 位数字均匀地散列成 8 位?
【发布时间】:2011-12-17 16:31:12
【问题描述】:

我正在寻找一种哈希算法,当给定一个 64 位的顺序值时,它会均匀地哈希到 8 位。

我不想只使用最低有效字节作为哈希值。

【问题讨论】:

  • “顺序值”是什么意思?你的意思是你实际上只是依次得到序列“0 1 2 3 4 5...”,并且你想将这些序列中的每一个散列为一个 8 位值?
  • 校验位合适吗?比如MOD 10?
  • 是的。它们是 64 位自动编号数据库主键。序列可能不是从 0 开始,但无论起始值是多少,序列对于每个后续值都是 +1。
  • 为什么你不想使用最低有效字节?如果你要拒绝最明显的方法,你应该解释它有什么不受欢迎的地方。
  • 同意。如果数字是连续的,那么只需取低字节即可将哈希冲突的数量保持在最低限度,那为什么不想要呢?

标签: c# hash integer


【解决方案1】:

作为 Oli Charlesworth 解决方案的一般情况,您可以选择与 256 互质,并将输入中的每个字节预乘以该值,然后将 XOR 所有值加在一起。你仍然会得到均匀分布,但对于顺序输入,你会得到非顺序输出,例如:

byte result = 0;
int q = 33149;
foreach (byte b in BitConverter.GetBytes(input)) result += (byte)(b * q);

对于 1, 2, 3, 4, 5, 6, ... 它会得到 125, 250, 119, 244, 113, 238 等

【讨论】:

  • 我的回答也会给出非顺序输出。
  • 同意,从 256 开始,您的版本也将获得不连续的结果,对于大于几千的值,它也会“看起来很随机”。
【解决方案2】:

缺乏任何进一步的信息或约束,一种可能性是将所有 8 个字节按位异或。对于统一的输入,这将是统一的。

我的 C# 生锈了,但在伪代码中:

byte hash = 0;
for (int i = 0; i < 8; i++) {
    hash ^= (byte)(val >> (i*8));
}

【讨论】:

  • 没有uint8,改用byte ;)
猜你喜欢
  • 2014-09-06
  • 1970-01-01
  • 2013-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-01
  • 1970-01-01
相关资源
最近更新 更多