c#中double数组的结构哈希

时间:2013-03-07 13:20:27

标签: c# .net hashcode

我想在C#数组中进行结构哈希,我不知道该怎么做。 在任何语言中,这似乎都是一个非常基本且非常简单的问题,但我无法在C#中使其工作...

我有383双数组。当我哈希它时,我得到一个非常奇怪的值

// this returns 134217728
let h = ((IStructuralEquatable) data).GetHashCode(EqualityComparer<double>.Default) 

恰好是ln h / ln 2 = 27 ...

如何在C#中获取可散列内容数组的结构哈希码?

修改更好的插图

特别是以下代码会产生愚蠢的结果

    var vala = new[] { 1f, 354652f, 3f };
    var valb = new[] { 1f, 56f, 545013f };
    var valc = new[] { 1f, 2584356483f,  68763948475f };

    var hashA = ((IStructuralEquatable)vala).GetHashCode(EqualityComparer<float>.Default);
    var hashB = ((IStructuralEquatable)valb).GetHashCode(EqualityComparer<float>.Default);
    var hashC = ((IStructuralEquatable)valc).GetHashCode(EqualityComparer<float>.Default);

哈希始终为796917760。 (它似乎随着第一个数字而变化......)

结论

结论似乎是实际上结构哈希在C#中被打破了。

(当然,有些人认为,几乎不变的函数是一个有效的哈希函数......)

2 个答案:

答案 0 :(得分:3)

您获得的价值并不奇怪,因为GetHashCode返回的值不透明。您不应该从它们派生任何信息,因此任何值都与其他值一样奇怪。

那就是说,IStructuralEquatable被视为解决问题的方法,而且确实对我有用:

var a = new[] { 1f, 2f, 3f };
var b = new[] { 1f, 2f, 3f };

var hashA=((IStructuralEquatable)a).GetHashCode(EqualityComparer<float>.Default);
var hashB=((IStructuralEquatable)b).GetHashCode(EqualityComparer<float>.Default);

Console.WriteLine(hashA == hashB); // true

答案 1 :(得分:1)

结构哈希码表示两个不同的对象(或集合)是否代表语义相同的数据。它工作正常;例如:

// invent some data
double[] vals1 = new double[383];
Random rand = new Random(12345);
for (int i = 0; i < vals1.Length; i++)
    vals1[i] = rand.NextDouble();
double[] vals2 = (double[])vals1.Clone();

// test with object rules
Console.WriteLine("{0} vs {1}",
    vals1.GetHashCode(), vals2.GetHashCode()); // 2 different numbers
Console.WriteLine(Equals(vals1, vals2)); // False

// now test using structural-equatable rules
IStructuralEquatable se1 = vals1, se2 = vals2;
var comparer = EqualityComparer<double>.Default;
Console.WriteLine("{0} vs {1}",
    se1.GetHashCode(comparer), se2.GetHashCode(comparer)); // 2 identical numbers
Console.WriteLine(se1.Equals(se2, comparer)); // True