我有一个很大的字典,其中的键是十进制,但是 System.Decimal 的 GetHashCode() 非常糟糕。为了证明我的猜测,我运行了一个包含 100.000 个相邻小数的 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);
这会打印 7。我不记得给了我 2 的起始小数点。
最佳答案
极其棘手的解决方案(但可能是最快的)
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;
}
}
// 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")));
关于c# - 将 System.Decimal 转换为 System.Guid,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3563830/