将System.Decimal转换为System.Guid

use*_*890 10 .net c# unsafe guid hashcode

我有一个大字典,其中键是十进制的,但System.Decimal的GetHashCode()非常糟糕.为了证明我的猜测,我运行了一个带有100.000 neigboring小数的for循环并检查了分布.100.000个不同的十进制数仅使用2个(两个!!!)不同的哈希码.

十进制表示为16个字节.就像Guid一样!但是Guid的GetHashCode()发行版非常好.如何在C#中将小数转换为Guid尽可能便宜? 不安全的代码没问题!


编辑:请求测试,所以这里是代码:

decimal d = 96000000000000000000m;
Dictionary<int, int> hashcount = new Dictionary<int, int>();
int length = 100000;
for (int i = 0; i < length; i++)
{
    int hashcode = d.GetHashCode();
    int n;
    if (hashcount.TryGetValue(hashcode, out n))
    {
        hashcount[hashcode] = n + 1;
    }
    else
    {
        hashcount.Add(hashcode, 1);
    }
    d++;
}

Console.WriteLine(hashcount.Count);
Run Code Online (Sandbox Code Playgroud)

这打印7.我不记得给我2的起始小数.

Tim*_*mwi 23

非常黑的解决方案(但可能最快)

public static class Utils
{
    [StructLayout(LayoutKind.Explicit)]
    struct DecimalGuidConverter
    {
        [FieldOffset(0)]
        public decimal Decimal;
        [FieldOffset(0)]
        public Guid Guid;
    }

    private static DecimalGuidConverter _converter;
    public static Guid DecimalToGuid(decimal dec)
    {
        _converter.Decimal = dec;
        return _converter.Guid;
    }
    public static decimal GuidToDecimal(Guid guid)
    {
        _converter.Guid = guid;
        return _converter.Decimal;
    }
}
Run Code Online (Sandbox Code Playgroud)
// Prints 000e0000-0000-0000-8324-6ae7b91d0100
Console.WriteLine(Utils.DecimalToGuid((decimal) Math.PI));

// Prints 00000000-0000-0000-1821-000000000000
Console.WriteLine(Utils.DecimalToGuid(8472m));

// Prints 8472
Console.WriteLine(Utils.GuidToDecimal(Guid.Parse("00000000-0000-0000-1821-000000000000")));
Run Code Online (Sandbox Code Playgroud)

  • @ user256890:既然你想要它尽可能快,那就再次使用同样的技巧:http://csharp.pastebin.com/Jqg9F9HA (4认同)

Jon*_*eet 5

如果您只是想获得不同的哈希算法,则无需转换为Guid.像这样的东西:

public int GetDecimalHashCode(decimal value)
{
    int[] bits = decimal.GetBits(value);
    int hash = 17;
    foreach (int x in bits)
    {
        hash = hash * 31 + x;
    }
    return hash;
}
Run Code Online (Sandbox Code Playgroud)

(如果你愿意,显然可以用不同的算法代替.)

不可否认,这仍然涉及创建一个不理想的阵列.如果你真的想创建一个Guid,你可以使用上面的代码来获取这些位,然后使用一个长的Guid构造函数从数组中传入适当的值.

我有点怀疑decimal哈希码是如此糟糕.你有一些示例代码吗?

  • 只需在字典构造函数中传递自定义IEqualityComparer即可 (3认同)
  • 在字典中存储`decimal`值时如何使用它?当然字典总是使用原始的`decimal :: GetHashCode()`? (2认同)