Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 将一个结构的一致散列设置为32位_.net_Hash - Fatal编程技术网

.net 将一个结构的一致散列设置为32位

.net 将一个结构的一致散列设置为32位,.net,hash,.net,Hash,我有一个结构,在[1,1000]和字符串中有3个整数 我需要用32位数字表示它,这样两个在至少一个字段中不同的结构将产生不同的代码,而具有相同内容的结构将一致地产生相同的代码。通常,其中一个整数字段将以几个单位递增。这必然会产生不同的代码 首先,我想将结构字段格式化为常量格式的字符串,然后使用string类的GetHashCode函数对其进行散列。但我在这里的一些讨论中读到,在同一个输入上运行的重复过程不一定会产生相同的散列输出。首先,这在.NET4中是真的吗?这对我来说很重要,因为散列值应该被

我有一个结构,在[1,1000]和字符串中有3个整数

我需要用32位数字表示它,这样两个在至少一个字段中不同的结构将产生不同的代码,而具有相同内容的结构将一致地产生相同的代码。通常,其中一个整数字段将以几个单位递增。这必然会产生不同的代码

首先,我想将结构字段格式化为常量格式的字符串,然后使用string类的GetHashCode函数对其进行散列。但我在这里的一些讨论中读到,在同一个输入上运行的重复过程不一定会产生相同的散列输出。首先,这在.NET4中是真的吗?这对我来说很重要,因为散列值应该被持久化,并且在进程运行期间保持一致。 我在这里还看到了使用素数对应用于每个结构字段的平台GetHashCode的结果执行位操作的建议。但在这里,显然我不能指望进程运行的一致结果

如果我使用加密哈希函数,我会超过32位

如果我没有一个字符串字段,我会将代码组成一个由数字字段组成的32位数组。用字符串字段GetHashCode结果对这样的位数组进行异或是否值得?我是否增加了对某些输入重复运行将产生相同哈希输出的机会


如果您有以下情况,您建议做什么?

struct 
{
    int A;
    int B;
    int C;
}

假设A、B、C在范围
[11000]
内。创建“完美散列”(无冲突)是可能的,因为a、B、C各有1000个不同的可能值。实际上,
log2(1000^3)匿名类型有一个自动生成的
GetHashCode()
实现。我会尝试使用:

struct MyStruct 
{
    int _intField1;
    int _intField2;
    int _intField3;
    string _stringField;

    public long GetHashCode() 
    {
        return new { _intField1, _intField2, _intField3, _stringField }.GetHashCode();
    }
}
由于
int
s和
string
s都是不可变的类型,因此只要底层.NET framework版本相同,应用程序运行之间的哈希代码应该保持不变。(这可能“不够持久”。)

也就是说,如果
GetHashCode()
的内部实现发生变化,它可能会发生变化。在这种情况下,请使用加密哈希。它是否超过32位并不重要,因为加密散列的设计目的是为输入的微小变化产生完全不同的输出。这意味着对于两个不同的输入,任何给定的32位哈希码都不太可能相等。只需使用将哈希的任意部分转换为
int

而且,很明显,这只会使两个不同的结构产生不同的散列码的可能性有所降低。(这可以通过使用生日悖论的近似公式来确定,如果我正确阅读wiki,这意味着一旦你存储了140000~30000条记录,你就有10%的机会获得副本。假设加密散列具有理想的属性。我不确定没有完美的散列你能做得更好。)

  • 将类型序列化为字节[]
  • 对字节[]应用公共哈希算法以获取哈希字节[]
  • 例如,拉出散列字节[]的前32位并使用该字节

  • 如果你想避免冲突,你需要一个完美的散列。你能用32位来唯一地描述你的每个结构吗?此外,对于内置哈希函数的稳定性,您没有任何保证(您也不应该这样做)。那么你用这个“散列”做什么呢?可能是@sixlettervariables的重复一个完美的散列需要事先知道整个值空间,对吗?(并且它包含少于2**32个元素。)@user2132086:这四个字段都是结构“标识”的一部分,还是其中一个或多个仅仅是一个“属性”(借用DB术语)?@PieterGeerkens是的,所有字段一起组合键搜索,因为有超过2**32个可能的文件,这种压缩算法可以证明是不存在的;)(好的,从技术上讲,压缩算法可以,只要你不需要解压算法。)@millimoose你是对的!让我们创建最强大的压缩算法:x=>0。@CédricBignon我的字符串字段表示一个机器名,因此可以进行一些假设,例如长度限制,但我不认为这有什么帮助:-)@user2132086除非字符串最多可以有4个不同的值,否则不能在32位上对此进行完美的哈希。(为什么是4?因为2^32/1000^3=4.29…。@millimoose如果我使用MD5Cng(我认为它应该更快),我可以假设其中的任何32位(我还不知道MD5Cng的通常结果有多大)是唯一的吗?@user2132086在防止冲突方面,较新的哈希(如SHA256)应该表现更好,但一般来说,是的。Wiki告诉我这个属性叫做,这是密码学研究人员有意实现的。其基本思想是,给定消息的哈希代码似乎也是随机确定的。现在很明显,如果从有限的值空间中随机选取,可能会发生冲突,但可以估计给定数目的选取的概率。@SixlettVariables我还没有太多证据来证明这一点,但我强烈怀疑匿名类型,特别是使用默认的
    GetHashCode()
    实现。它们当然会自动生成
    Equals()
    的“合理”实现,这意味着它们还应该自动生成一个类似的
    GetHashCode()
    实现,该实现主要用于字段的hashcode(在本例中都是值类型)。我敢打赌,至少在.NET framework版本的生命周期内,这些值是稳定的。@SixlettVariables并查看匿名类型的反编译源代码,其
    GetHashCode()
    实现中使用的只是一组编译时常量,以及
    EqualityComparer.Default.GetHashCode
    
    int MyHashCode()
    {
        return 1001 * (1001 * A + B) + C;  // There is no overflow or collision since A, B, C are in the range [0, 1000]
    }
    
    struct MyStruct 
    {
        int _intField1;
        int _intField2;
        int _intField3;
        string _stringField;
    
        public long GetHashCode() 
        {
            return new { _intField1, _intField2, _intField3, _stringField }.GetHashCode();
        }
    }