Jan*_*nes 42 .net c# hash decimal
我们碰到了一个神奇的十进制数字,打破了我们的哈希表.我把它归结为以下最小的情况:
decimal d0 = 295.50000000000000000000000000m;
decimal d1 = 295.5m;
Console.WriteLine("{0} == {1} : {2}", d0, d1, (d0 == d1));
Console.WriteLine("0x{0:X8} == 0x{1:X8} : {2}", d0.GetHashCode(), d1.GetHashCode()
, (d0.GetHashCode() == d1.GetHashCode()));
Run Code Online (Sandbox Code Playgroud)
给出以下输出:
295.50000000000000000000000000 == 295.5 : True
0xBF8D880F == 0x40727800 : False
Run Code Online (Sandbox Code Playgroud)
真正奇怪的是:更改,添加或删除d0中的任何数字,问题就会消失.甚至添加或删除其中一个尾随零!这个标志似乎并不重要.
我们的解决方法是将值除去以消除尾随零,如下所示:
decimal d0 = 295.50000000000000000000000000m / 1.000000000000000000000000000000000m;
Run Code Online (Sandbox Code Playgroud)
但我的问题是,C#怎么做错了?
Jon*_*eet 27
首先,C#完全没有做错任何事情.这是一个框架错误.
它确实看起来像一个bug - 基本上,比较相等所涉及的规范化应该以相同的方式用于哈希码计算.我已经检查过并且可以重现它(使用.NET 4),包括检查Equals(decimal)
和Equals(object)
方法以及==
操作符.
它肯定看起来像是问题的d0
价值,因为添加尾随0 d1
不会改变结果(直到它d0
当然是相同的).我怀疑那里有一些角落案例被那里的确切位代表所绊倒.
我很惊讶它不是(正如你所说,它大部分时间都有效),但你应该报告Connect上的错误.