Rol*_*kas 9 .net double decimal gethashcode
为什么
17m.GetHashCode() == 17d.GetHashCode()
(m =十进制,d =双)
此外,正如预期的那样
17f.GetHashCode() != 17d.GetHashCode()
(f =浮点数)
对于net3.5和net4.0来说,这似乎都是正确的.
据我了解,这些类型的内部位表示是完全不同的.那么为什么十进制和双精度类型的哈希码对于相等的初始化值相等呢?在计算哈希值之前是否发生了一些转换?
我发现源代码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));
}
Run Code Online (Sandbox Code Playgroud)
我验证了此代码返回了所需的值.但我没有找到源代码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]);
}
Run Code Online (Sandbox Code Playgroud)
但是这与期望的结果不匹配(它返回了对应于int类型的哈希值,考虑到十进制的内部布局,这也是预期的).所以Decimal.GetHashCode()遗体的实施目前我不知道.
Decimal.GetHashCode()方法在CLR中实现.您可以从SSCLI20源代码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];
Run Code Online (Sandbox Code Playgroud)
否则,这与C#中的Double.GetHashCode()实现完全等效,但是用C++编写,因此获得匹配并不是意料之外的. VarR8FromDec()是一个COM自动化辅助函数,它将COM DECIMAL转换为double.
当然,永远不要依赖这样的比赛.
更新:现在CLR是开源的,在这个github文件中可见,它看起来仍然相同.一个问题是VarR8FromDec()是一个Windows功能,在Linux或OSX中不可用,它在PAL中重新实现.
| 归档时间: |
|
| 查看次数: |
1916 次 |
| 最近记录: |