2010-03-19 11 views
7

Las variantes OLE, como las utilizadas en versiones anteriores de Visual Basic y de forma generalizada en COM Automation, pueden almacenar muchos tipos diferentes: tipos básicos como enteros y flotantes, tipos más complicados como cadenas y matrices y hasta IDispatch implementaciones y punteros en forma de variantes ByRef.¿Cuál es la implementación recomendada para hashing OLE variantes?

Las variantes también se tipan débilmente: convierten el valor a otro tipo sin previo aviso según el operador que aplique y los tipos actuales de los valores pasados ​​al operador. Por ejemplo, al comparar dos variantes, una que contiene el número entero 1 y otra que contiene la cadena "1", para la igualdad devolverá True.

Así que asumiendo que estoy trabajando con variantes a nivel de datos subyacente (por ejemplo VARIANT en C++ o TVarData en Delphi - es decir, la gran unión de diferentes valores posibles), ¿cómo debo hash de variantes constantemente para que obedezcan la derecha ¿reglas?

Reglas:

  • variantes que hash de manera desigual debe comparar tan desigual, tanto en la clasificación y la igualdad directa
  • variantes que resultan ser iguales tanto para la clasificación y la igualdad directa debe desmenuzar como igual

Está bien si tengo que usar diferentes reglas de clasificación y comparación directa para que el hash se ajuste.

La forma en que estoy trabajando actualmente es que estoy normalizando las variantes de las cadenas (si encajan), y tratándolas como cadenas, de lo contrario estoy trabajando con la variante de datos como si fuera una burbuja opaca, y hashing y comparando sus bytes brutos. Eso tiene algunas limitaciones, por supuesto: los números 1..10 ordenan como [1, 10, 2, ... 9] etc. Esto es levemente molesto, pero es consistente y es muy poco trabajo. Sin embargo, me pregunto si hay una práctica aceptada para este problema.

+1

VARIANT es en realidad una estructura, que tiene dos datos: valor y tipo. Su reclamo de comparación y conversión parece tomar en consideración solo el valor y no observa el tipo archivado de esa estructura. El enfoque correcto es siempre considerar el tipo archivado también. –

+1

@Franci, creo que te perdiste el punto. Dos variantes pueden comparar igual incluso cuando sus tipos difieren. Si las variantes son iguales, Barry también quiere que sus hash sean iguales. 'Variant (1) = Variant ('1')' ==> 'hash (Variant (1)) = hash (Variant ('1'))'. –

+1

Barry, no creo que tu primera regla sea correcta. Ignora la posibilidad de colisiones hash, donde los hash son iguales pero los valores no son similares en absoluto. –

Respuesta

0

Los códigos hash de VARIANTS que son iguales deben ser iguales.

Sin conocer las reglas de igualdad y coacción que se utilizan para probar la igualdad, es difícil encontrar una implementación adecuada.

+0

Estoy muy familiarizado con el funcionamiento de los códigos hash.NET y Java (he escrito compiladores tanto para la CLR como para JVM), pero el problema es que las variantes utilizadas en VB y Delphi no son seguras para el tipo de la misma manera que los objetos polimórficos almacenados en una ubicación de tipo Object en .NET o Java, o la forma en que los valores son seguros en Ruby, Python o Javascript. Es decir, '1 ==" 1 "', o '1.Equals (" 1 ") == verdadero', para los valores de Variant de' 1' y '" 1 "'. Supongo que la respuesta a mi pregunta es "depende", según la semántica del lenguaje. –

+0

Estoy marcando esta respuesta, ya que es bastante cierto, para poder escribir la función hash que garantiza que coincide con la función de igualdad, la función de igualdad debe conocerse y estar bien definida. –

0

Por lo tanto, en resumen, para hacer que las cosas sean comparables, primero transmita a un formato, cadena o blob común.

¿Cómo se maneja, por ejemplo,? localización, p. formateo de reales? Un real en comparación con una cadena que contenga el mismo real creado en otra configuración regional fallará. O un real escrito en una cadena con una configuración de precisión diferente.

Me parece que la definición de igual() es el problema, no el hashing. Si los valores "iguales" se pueden serializar a cadena (o blob) de manera diferente, el hash fallará.

+0

Ese es un buen punto. Hay dos respuestas posibles: (a) usar configuraciones invariables para que los códigos hash sean confiables en múltiples instancias y locales, etc., o (b) no importa, siempre y cuando los resultados sean consistentes dentro de cualquier ejecución dada (aunque la configuración puede cambiar y romper cosas en casos extremos). Dado todo lo que se ha dicho en los comentarios a mi pregunta - Me gustaría que más de esos comentarios fueran respuestas reales - Puedo revisar mi enfoque y manejar los tipos de forma individual, y no tratar de preservar la semántica de igualdad de Delphi al considerar comparadores, etc. para algoritmos. –

2

Hay una tensión incorporada en su pregunta entre el uso de una función hash y los requisitos establecidos, que se validan contra la entrada del hash. Sugiero que tengamos en cuenta algunas propiedades de hashes en general: se pierde información durante el proceso de hashing y se esperan colisiones hash. Es posible construir un hash perfecto sin colisiones, pero sería problemático (¿o imposible?) Construir una función hash perfecta si el dominio de la función es cualquier posible variante OLE. Por otro lado, si no estamos hablando de un hash perfecto, entonces se viola su primera regla.

No conozco el contexto más amplio de lo que está tratando de lograr, pero debo retroceder en una de sus suposiciones: ¿es realmente una función hash lo que quiere? Sus requisitos podrían cumplirse de una manera bastante directa si desarrolla un sistema que codifica, no hash, todos los posibles atributos de variante OLE para que puedan recuperarse posteriormente y compararse con otras imágenes de variante.

Su implementación de línea base para convertir la variante en una representación de cadena se mueve en esta dirección. Como sin duda sabe, una Variante puede contener punteros, punteros dobles y matrices, por lo que deberá desarrollar una representación de cadenas consistente de estos tipos de datos. Me pregunto si este enfoque realmente podría clasificarse como un hash. ¿No estás simplemente persistiendo en los atributos de datos?

+0

Escribo una clase de colección genérica para una biblioteca en tiempo de ejecución. El parámetro genérico podría ser una variante. El hash perfecto no es relevante. (De hecho, el hash perfecto puede ser contraproducente en tablas hash pequeñas al aumentar el costo de una búsqueda fallida de hash). –

Cuestiones relacionadas