在 Delphi 中将 GetHashCode 的双精度数转换为整数
Delphi 2009为TObject添加了GetHashCode函数。 GetHashCode 返回一个 Integer,用于 TDictionary 中的散列。
如果您希望对象在 TDictionary 中正常工作,则需要适当地重写 GetHashCode,以便通常不同的对象返回不同的整数哈希代码。
但是对于包含双字段的对象该怎么办呢?如何将这些双精度值转换为 GetHashCode 的整数?
例如,在 Java 中通常完成的方式是使用 Double.doubleToLongBits 或 Float.floatToIntBits 等方法。后者的文档描述如下:“根据 IEEE 754 浮点“单一格式”位布局返回指定浮点值的表示形式。”这涉及对浮点值的不同位使用不同掩码的一些按位运算。
Delphi中有没有这样的函数?
Delphi 2009 added the GetHashCode function to TObject. GetHashCode returns an Integer which is used for hashing in TDictionary.
If you want an object to work well in TDictionary, you need to override GetHashCode appropriately such that, in general, different objects return different integer hash codes.
But what do you do for objects containing double fields? How do you turn those double values into a integers for GetHashCode?
The way it's usually done in Java, say, is to use a method like Double.doubleToLongBits or Float.floatToIntBits. The latter has documentation that describes it as follows: "Returns a representation of the specified floating-point value according to the IEEE 754 floating-point "single format" bit layout." This involves some bitwise operations with different masks for the different bits of a floating point value.
Is there a function that does this in Delphi?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我建议对 Gamecat 代码进行以下改进:
这考虑了 Double 值的所有位。
(注释与代码不能很好地配合)
I'd suggest the following improvement over the Gamecat code:
This takes into account all the bits of the Double value.
(comments do not work well with code)
如果要将双精度数映射到整数,可以使用变体记录:
请注意,这会执行按位复制而不解释值。
另一种(肮脏的伎俩,是使用绝对变量:
If you want to map a double to an integer, you can use a variant record:
Beware that this does a bitwise copy without interpretation of the values.
Another (kind of dirty trick, is using absolute variables:
实际上没有必要做这样的事情,因为 GetHashCode 的默认值已经返回一个保证每个对象都是唯一的数字:对象的内存地址。此外,如果您更改对象包含的数据,默认哈希值也不会更改。
假设您有一个包含值为 3.5 的 Double 的对象,您对它进行哈希处理并将其放入字典中,您将获得哈希码 12345678。您还有其他对象保存对它的引用,并且该 Double字段发生更改,现在其值为 5.21。下次您尝试计算其哈希值时,您的哈希代码现在为 23456789,并且您的查找将失败。
除非您可以保证这种情况永远不会发生,并且您有充分的理由不使用内存地址,否则最好的选择是保持 GetHashCode 不变。 (如果它没有坏,就不要修理它。)
There's really no need to do something like this, because the default value of GetHashCode already returns a number that's guaranteed to be unique for each object: the object's memory address. Furthermore, the default hash value isn't going to change if you change the data your object contains.
Let's say you have an object that contains a Double with a value of 3.5, and you hash it and put it into a dictionary, and you get a hash code of 12345678. You also have something else holding a reference to it, and that Double field gets changed and now it's got a value of 5.21. Next time you attempt to calculate its hash value, your hash code is now 23456789, and your lookup will fail.
Unless you can guarantee that this will never happen, and you have a really good reason not to use the memory address, your best bet is to just leave GetHashCode as it is. (If it ain't broke, don't fix it.)
我想 Java 的东西可以在 Delphi 中实现,如下所示:
背后的想法是降低 Double 值的精度以匹配 Integer 的二进制大小 (Sizeof(Single) = Sizeof(Integer))。如果您的值可以用单精度表示而不会发生冲突,那么这将给出一个很好的哈希值。
编辑:由于类型转换无法在我的 D2009 中编译,我调整了变体记录解决方案。
I guess the Java thing can be implemented in Delphi like this:
The idea behind is to reduce the precision of the Double value to match the binary size of an Integer (Sizeof(Single) = Sizeof(Integer)). If your values can be represented in Single precision without collision, this will give a good hash value.
Edit: As the typecast won't compile in my D2009, I adapted the variant record solution.
对 Double 数据使用 CRC32,因为 xor 是邪恶的。
Use CRC32 on the Double data because xor is evil.