我正在使用MD5算法来散列磁盘哈希表的密钥(我知道这是否是用于此的最佳算法是值得怀疑的,但我现在正在使用它。问题是可以推广到任何产生字节数组的算法。我的问题是:
哈希码的大小决定了哈希表中组合(桶)的数量。由于MD5是128位,因此有很多组合(~3.4e38),这对我来说太大了。所以我想要做的是选择MD5产生的字节数组的前n位,并将它们转换为长(或ulong)值。由于MD5产生一个字节数组,如果我想要一个整数个字节就很容易做到,但这会导致组合数量的跳跃太大。我发现单位版本要复杂得多。
目标:
n = 10 // I.e. I want 2^10 combinations
long pos = someFcn(byte[] key, n)
其中key是被散列的值,n是我想要使用的MD5结果的位数。然后,Pos将是0到1023之间的整数(在n = 10的情况下)。如果n = 11,则代码将从0到2 ^ 11-1 = 2027等。必须有点快/高效。
看起来不那么难,但它让我望而却步。任何帮助将非常感激。谢谢。
答案 0 :(得分:1)
首先,将前四个字节转换为一个整数,BitConverter.ToInt32
。它无论如何都会得到四个字节,但这可能不会让它慢得多,因为无论如何你都在使用32位寄存器进行其余的计算,而且复杂的东西比如“如果它是< 16那么这样做前两个字节“只会使它更复杂
然后,给定该整数,取最低N位。如果你真的想要在编译时不知道特定数量的位[两个桶的功率],~((-1)<<N)
是获得2 ^ N-1的好方法。
或者你可以简单地使用ToUInt32
代替模数素数[转换为UInt64可能稍好一些,那么你可以在这种情况下完全占据一半的位数]
答案 1 :(得分:0)
获取前10位,例如:
int result = ((int)key[0] << 2) | (((int)key[1] >> 6) & 0x03)
答案 2 :(得分:0)
如果您有这样的数组,
unsigned char data[2000];
然后你可以把前n位刮掉一个像这样的整数:
typedef unsigned long long int MyInt;
MyInt scrape(size_t n, unsigned char * data)
{
MyInt result = 0;
size_t b;
for (b = 0; b < n / 8; ++b)
{
result <<= 8;
result += data[b];
}
const size_t remaining_bits = n % 8;
result <<= remaining_bits;
result += (data[b] >> (8 - remaining_bits));
return result;
}
我假设CHAR_BITS == 8
,如果您愿意,可以随意概括代码。此外,数组的大小乘以8必须至少为n
。