C# 将部分MD5哈希代码转换为长

C# 将部分MD5哈希代码转换为长,c#,arrays,hash,byte,md5,C#,Arrays,Hash,Byte,Md5,我正在使用MD5算法对磁盘哈希表的键进行散列(我知道这是否是用于此目的的最佳算法值得怀疑,但我现在就使用它。这个问题可以推广到任何生成字节数组的算法)。我的问题是: 哈希代码的大小决定了哈希表中的组合(桶)数量。因为MD5是128位的,所以有大量的组合(~3.4e38),这对于我来说太大了。所以我想做的是从MD5生成的字节数组中提取前n位,并将它们转换成一个长(或ulong)值。由于MD5生成一个字节数组,如果我想要整数个字节,这将很容易做到,但这会导致组合数量的大幅增加。我发现单比特版本要复杂

我正在使用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,等等。必须稍微快速/高效


看起来没那么难,但我还是逃避不了。任何帮助都将不胜感激。谢谢

获取前10位,例如:

int result = ((int)key[0] << 2) | (((int)key[1] >> 6) & 0x03)
int结果=((int)键[0]>6)和0x03)

获取前10位,例如:

int result = ((int)key[0] << 2) | (((int)key[1] >> 6) & 0x03)
int结果=((int)键[0]>6)和0x03)

首先,将前四个字节转换为整数,使用。不管怎样,它都会得到四个字节,但这可能不会使它的速度明显变慢,因为在剩下的计算中,您使用的是32位寄存器,而复杂的东西,如“如果小于16,那么使用前两个字节执行此操作”只会使它变得更复杂


然后,给定该整数,取最低的N位。如果您确实希望编译时不知道特定位数[两个存储桶的幂]的话,
~(-1)首先,将前四个字节转换成一个整数,使用。不管怎样,它都会得到四个字节,但这可能不会使它变得更慢,因为在剩下的计算中,您使用的是32位寄存器,以及复杂的东西,如“如果小于16,则对前两个字节执行此操作”只会让事情变得更复杂


然后,给定该整数,取最小的N位。如果您确实想要编译时未知的特定位数[两个桶数的幂],如果您有这样一个数组

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;
 }
typedef无符号长整型MyInt;
MyInt刮取(大小,无符号字符*数据)
{
MyInt结果=0;
尺寸b;
对于(b=0;b结果如果你有这样一个数组

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;
 }
typedef无符号长整型MyInt;
MyInt刮取(大小,无符号字符*数据)
{
MyInt结果=0;
尺寸b;
对于(b=0;b结果你需要一些位移位。我不知道C#语法,但是。你需要一些位移位。但是我不知道C#语法。有符号整数上的右移位定义得好吗?它不在C中,但我不知道C#。是的,它定义得好。新的位与符号位相同。有符号整数上的右移位定义得好吗?没有在C中,但我不知道C#。是的,它定义得很好。新的位与符号位相同。非常好。谢谢,Random832等。将使用非常简单的东西,如:UInt64 pos=42;UInt64 mask=~(-1)如果你对数字进行硬编码,我建议只硬编码15或0xF,“技巧”是针对N是可变的情况。非常好。谢谢,Random832等。将使用非常简单的方法,如:UInt64 pos=42;UInt64 mask=~(-1)如果你要硬编码这个数字,我建议你只硬编码15或0xF,这个“技巧”是指如果N是可变的。