我想在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#中被打破了。
(当然,有些人认为,几乎不变的函数是一个有效的哈希函数......)
答案 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