首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C# Decimal.GetHashCode()和Double.GetHashCode()相等

C# Decimal.GetHashCode()和Double.GetHashCode()相等
EN

Stack Overflow用户
提问于 2012-09-02 13:53:16
回答 1查看 2.6K关注 0票数 9

为什么

17m.GetHashCode() == 17d.GetHashCode()

(m=decimal,d=double)

此外,如预期的那样

17f.GetHashCode() != 17d.GetHashCode()

(f=float)

对于net3.5和net4.0来说,这似乎都是正确的。

据我所知,这些类型的内部位表示是非常不同的。那么,为什么十进制类型的哈希码对于相同的初始化值相等呢?在计算散列之前是否进行了一些转换?

我发现Double.GetHashCode()的源代码如下:

代码语言:javascript
复制
//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()的源代码。我试着用方法

代码语言:javascript
复制
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类型对应的散列,这也是考虑到十进制内部布局的情况)。因此,Decimal.GetHashCode()的实现对我来说仍然是未知的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-09-02 15:12:27

Decimal.GetHashCode()方法是在CLR中实现的。您可以从SSCLI20源代码clr/vm/com.jal.cpp获得可能的实现:

代码语言:javascript
复制
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];

否则,这与C#中的C#实现完全相同,但它是用C++编写的,因此获得匹配并不是意料之外的。VarR8FromDec()是一个COM自动化助手函数,它将COM十进制转换为双进制。

当然,永远不要依赖这样的匹配。

更新:既然CLR是开源的,在这个github文件中是可见的,它看起来还是一样的。一个缺点是VarR8FromDec()是一个在Linux或OSX中不可用的在PAL中重新实现函数,它是在PAL中重新实现

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12236499

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档