【问题标题】:What's the recommended implementation for hashing OLE Variants?散列 OLE 变体的推荐实现是什么?
【发布时间】:2011-01-29 14:12:02
【问题描述】:

OLE 变体,被旧版本的 Visual Basic 使用并且在 COM 自动化中普遍使用,可以存储许多不同的类型:基本类型,如整数和浮点数,更复杂的类型,如字符串和数组,一直到 @987654321 @ 实现和ByRef 变体形式的指针。

变体也是弱类型的:它们将值转换为另一种类型而不会发出警告,具体取决于您应用的运算符以及传递给运算符的值的当前类型。例如,比较两个变量,一个包含整数 1,另一个包含字符串 "1",如果相等,将返回 True

因此,假设我在底层数据级别使用变体(例如 C++ 中的 VARIANT 或 Delphi 中的 TVarData - 即不同可能值的大联合),我应该如何一致地散列变体以便它们遵守正确的规则?

规则:

  • 散列不相等的变体在排序和直接相等时都应该比较为不相等
  • 对于排序和直接相等比较为相等的变体应哈希为相等

如果我必须使用不同的排序和直接比较规则以使散列适合,那也没关系。

我目前的工作方式是将变体规范化为字符串(如果它们适合),并将它们视为字符串,否则我正在处理变体数据,就好像它是一个不透明的 blob 一样,并散列并比较其原始字节。当然,这有一些限制:数字1..10 排序为[1, 10, 2, ... 9] 等。这有点烦人,但它是一致的,而且工作量很小。但是,我确实想知道这个问题是否有公认的做法。

【问题讨论】:

  • VARIANT 实际上是一个结构,它有两个数据——值和类型。您的比较和转换声明似乎只考虑了值,而不考虑该结构的类型字段。正确的方法是始终考虑提交的类型。
  • @Franci,我认为你没有抓住重点。即使它们的类型不同,两个变体也可以比较相等。如果变体比较相等,那么 Barry 也希望它们的哈希值相等。 Variant(1) = Variant('1') ==> hash(Variant(1)) = hash(Variant('1')).
  • 巴里,我不认为你的第一条规则是正确的。它忽略了散列冲突的可能性,其中散列相等但值根本不相似。
  • 你说得对@Rob,我的意思是相反的——我把它倒过来了。虽然我认为它实际上遵循第二条规则。
  • 如果 Barry 想要语义相等,即任何 VARIANT 类型中数字 1 的任何表示都被视为相同(包括字符串、日期和对象(无论如何,1 的 IDispatch 或 OLEDATE 表示是什么?) ) 并且要具有相同的散列,他应该在计算散列时考虑类型,或者应该将所有表示“标准化”为相同的数据类型(他目前似乎正在这样做)。如果他选择“规范化”方法,则 VARIANT 部分与问题绝对无关,因为同样的问题适用于他选择的任何其他值存储。

标签: c++ delphi winapi com variant


【解决方案1】:

因此,总而言之,要使内容具有可比性,您首先要以通用格式、字符串或 blob 流式传输。

您如何处理本地化,例如实数的形成?与在另一个语言环境中创建的包含相同实数的字符串相比,实数将失败。或者一个真正的写入到不同精度设置的字符串。

在我看来,equal() 的定义是问题所在,而不是散列。如果“相等”的值可以以不同的方式序列化为字符串(或 blob),则散列将失败。

【讨论】:

  • 这很好。有两个可能的答案:(a)使用不变的设置,以便哈希码在多个实例和语言环境等中是可靠的,或者(b)只要结果在任何给定的运行中都是一致的(尽管设置可能在极端情况下改变和破坏事物)。鉴于 cmets 中对我的问题所说的所有内容 - 我希望更多这些 cmets 是实际答案 - 我可能会审查我的方法并单独处理类型,而不是在考虑算法所需的比较器等时尝试保留类似 Delphi 的相等语义.
【解决方案2】:

相等的VARIANTS的哈希码应该相等。

如果不知道用于测试相等性的相等和强制规则,就很难提出适当的实现。

【讨论】:

  • 我非常熟悉哈希码在 .NET 和 Java 中的工作原理(我已经编写了同时针对 CLR 和 JVM 的编译器),但问题是在 VB 和 Delphi 中使用的变体与存储在 .NET 或 Java 中的 Object 类型位置中的多态对象的类型安全不同,或者值在 Ruby、Python 或 Javascript 中的类型安全方式不同。即,1 == "1"1.Equals("1") == true,用于变量值 1"1"。我想我的问题的答案是“取决于”——取决于语言语义。
  • 我将这个答案标记为非常正确,为了编写保证与相等函数匹配的哈希函数,必须知道相等函数并明确定义。
【解决方案3】:

在您的问题中,哈希函数的使用与规定的要求之间存在内在张力,这些要求是针对哈希输入进行验证的。我建议我们牢记哈希的一些一般属性:在哈希过程中会丢失信息,并且可以预料到哈希冲突。可以构造一个没有冲突的完美散列,但是如果函数的域是任何可能的 OLE 变体,那么构造一个完美的散列函数就会有问题(或不可能?)。另一方面,如果我们不是在谈论完美哈希,那么您的第一条规则就被违反了。

我不知道你想要完成什么的更大背景,但我必须推翻你的一个假设:哈希函数真的是你想要的吗?如果您开发的系统可以对所有可能的 OLE Variant 属性进行编码而不是散列,以便稍后调用它们并与其他 Variant 图像进行比较,那么您的要求可以相当直接地得到满足。

您将 Variant 转换为字符串表示的基线实现正在朝这个方向发展。毫无疑问,Variant 可以包含指针、双指针和数组,因此您必须为这些数据类型开发一致的字符串表示。我质疑这种方法是否真的可以归类为哈希。不就是持久化数据属性吗?

【讨论】:

  • 我正在为运行时库编写一个通用集合类。通用参数可能是一个变体。完美的散列是不相关的。 (实际上,完美的哈希在小型哈希表中会适得其反,因为它会增加失败的哈希查找成本。)
猜你喜欢
  • 1970-01-01
  • 2022-12-11
  • 1970-01-01
  • 1970-01-01
  • 2011-07-17
  • 2021-09-16
  • 1970-01-01
  • 1970-01-01
  • 2011-10-18
相关资源
最近更新 更多