-1

I would like to do structural hashing in a C# array, and I dont know how to do so. This seems like a very basic and very simple question in any language, but I can't make it work in C#...

I have an array of 383 double. when I hash it, I get a very odd value

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

which happens to be such that ln h / ln 2 = 27 ...

How can one get in C# the structural hashcode of an array of hashable stuff ?

Edit better illustration

In particular the following code would produce stupid results

    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);

the hash is consistently 796917760. (it seem to change with the 1st number though...)

Conclusion

The conclusion seems to be that structural hashing is just broken in C#, in practical terms.

(of course litterally, it is not, as others have argued an almost constant function is a valid hash function.....)

4

2 回答 2

3

The value you get is not really odd because values returned by GetHashCode are opaque. You are not supposed to be able to derive any information from them, so any value is as odd as any other.

That said, IStructuralEquatable is billed as the solution to your problem, and indeed it works for me:

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
于 2013-03-07T13:22:15.533 回答
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
于 2013-03-07T13:35:41.600 回答