为什么会这样
17m.GetHashCode() == 17d.GetHashCode()
(m=十进制,d=双精度)
另外,正如预期的那样
17f.GetHashCode() != 17d.GetHashCode()
(f=浮点数)
对于 net3.5 和 net4.0 来说似乎都是如此。
据我了解,这些类型的内部位表示有很大不同。那么为什么哈希码是decimal and double相同的初始化值的类型是否相等?在计算哈希值之前是否发生了一些转换?
我发现源代码为Double.GetHashCode()
这是:
//The hashcode for a double is the absolute value of the integer representation
//of that double.
//
[System.Security.SecuritySafeCritical] // auto-generated
public unsafe override int GetHashCode() {
double d = m_value;
if (d == 0) {
// Ensure that 0 and -0 have the same hash code
return 0;
}
long value = *(long*)(&d);
return unchecked((int)value) ^ ((int)(value >> 32));
}
我验证了这段代码返回了所需的值。但我没有找到源代码Decimal.GetHashCode()
。我尝试使用方法
public static unsafe int GetHashCode(decimal m_value) {
decimal d = m_value;
if (d == 0) {
// Ensure that 0 and -0 have the same hash code
return 0;
}
int* value = (int*)(&d);
return unchecked(value[0] ^ value[1] ^ value[2] ^ value[3]);
}
但这与期望的结果不匹配(它返回了与int
类型,考虑到这也是预期的小数的内部布局 http://msdn.microsoft.com/en-us/library/system.decimal.getbits.aspx)。所以实施Decimal.GetHashCode()
目前我仍然不知道。
Decimal.GetHashCode() 方法在 CLR 中实现。您可以查看possibleSSCLI20 源代码 clr/vm/comdecimal.cpp 的实现:
double dbl;
VarR8FromDec(d, &dbl);
if (dbl == 0.0) {
// Ensure 0 and -0 have the same hash code
return 0;
}
return ((int *)&dbl)[0] ^ ((int *)&dbl)[1];
否则,这与Double.GetHashCode() http://referencesource.microsoft.com/#mscorlib/system/double.cs,01ee10483fa0a3ad用 C# 实现,但用 C++ 编写,因此获得匹配并不意外。VarR8FromDec() http://technet.microsoft.com/en-us/library/ms221523%28v=VS.85%29.aspx是一个 COM 自动化辅助函数,它将 COM DECIMAL 转换为双精度。
当然,never就靠这样的搭配。
更新:现在 CLR 是开源的,它看起来仍然一样,在这个github文件 https://github.com/dotnet/coreclr/blob/master/src/classlibnative/bcltype/decimal.cpp。一个问题是 VarR8FromDec() 是一种 Windows 函数,在 Linux 或 OSX 中不可用,它是在PAL中重新实现 https://github.com/dotnet/coreclr/blob/master/src/palrt/decconv.cpp.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)