2010-03-19 12 views
7

OLE-Varianten, wie von älteren Versionen von Visual Basic und pervasiv in COM Automation verwendet, können viele verschiedene Typen speichern: grundlegende Typen wie Ganzzahlen und Gleitkommazahlen, kompliziertere Typen wie Strings und Arrays und bis zu IDispatch Implementierungen und Zeiger in Form von Varianten.Was ist die empfohlene Implementierung für Hash-OLE-Varianten?

Varianten sind auch schwach typisiert: Sie konvertieren den Wert in einen anderen Typ ohne Warnung abhängig davon, welchen Operator Sie anwenden und welche die aktuellen Typen der Werte sind, die an den Operator übergeben werden. Wenn Sie beispielsweise zwei Varianten vergleichen, von denen eine die Ganzzahl 1 enthält und eine andere die Zeichenfolge "1" enthält, wird True zurückgegeben.

So davon aus, dass ich mit Varianten in der zugrunde liegenden Datenebene (zB VARIANT in C++ oder TVarData in Delphi - also die großen Vereinigung von verschiedenen möglichen Werten) gerade arbeitete, wie soll ich Hash konsequent Varianten, so dass sie das Recht zu gehorchen Regeln?

Regeln:

  • Varianten, die Hash-ungleicher als ungleich, sowohl in Sortier- und direkte Gleichheit
  • Varianten, die sowohl für das Sortieren und direkte Gleichheit sollte gleich
Hash als gleich vergleichen Vergleichen sollte

Es ist in Ordnung, wenn ich verschiedene Sortier- und direkte Vergleichsregeln verwenden muss, um das Hashing fit zu machen.

Die Art, wie ich gerade arbeite, ist, dass ich die Varianten zu Strings normalisiere (wenn sie passen), und sie als Strings behandle, sonst arbeite ich mit den Variantendaten, als ob es ein undurchsichtiger Fleck wäre, und Hashing und Vergleich seiner rohen Bytes. Das hat natürlich einige Einschränkungen: Nummern 1..10 Sortierung als [1, 10, 2, ... 9] etc. Das ist leicht nervig, aber es ist konsistent und es ist sehr wenig Arbeit. Ich frage mich jedoch, ob es für dieses Problem eine akzeptierte Praxis gibt.

+1

VARIANT ist eigentlich eine Struktur, die zwei Daten - Wert und Typ hat. Ihr Vergleichs- und Conversion-Anspruch scheint nur den Wert zu berücksichtigen und schaut nicht auf den Typbereich dieser Struktur. Der richtige Ansatz besteht darin, immer auch den Typ zu berücksichtigen. –

+1

@Franci, ich denke du hast den Punkt verpasst. Zwei Varianten können gleich sein, selbst wenn sich ihre Typen unterscheiden. Wenn die Varianten gleich sind, dann wünscht Barry, dass ihre Hashes auch gleich sind. 'Variante (1) = Variante ('1')' ==> 'hash (Variante (1)) = hash (Variante ('1'))'. –

+1

Barry, ich glaube nicht, dass deine erste Regel richtig ist. Es ignoriert die Möglichkeit von Hash-Kollisionen, bei denen die Hashwerte gleich sind, aber die Werte überhaupt nicht ähnlich sind. –

Antwort

0

Hash-Codes von VARIANTS, die gleich sind, sollten gleich sein.

Ohne die Gleichheits- und Zwangsregeln zu kennen, die für die Prüfung der Gleichheit verwendet werden, ist es schwierig, eine korrekte Implementierung zu finden.

+0

Ich bin sehr vertraut mit der Funktionsweise von Hashcodes.NET und Java (Ich habe Compiler in beide CLR und JVM geschrieben), aber das Problem ist, dass Varianten wie in VB und Delphi sind nicht typsicher auf die gleiche Weise wie polymorphe Objekte an einem Speicherort des Typs Objekt in gespeichert .NET oder Java oder die Art, wie Werte in Ruby, Python oder Javascript typsicher sind. Das heißt, 1 == "1", oder "1.Equals (" 1 ") == wahr", für Variantenwerte von "1" und "1". Ich denke die Antwort auf meine Frage ist "es kommt darauf an" - abhängig von der Semantik der Sprache. –

+0

Ich markiere dies die Antwort, da es ziemlich wahr ist, um die Hash-Funktion zu schreiben, die garantiert die Gleichheitsfunktion übereinstimmen, muss die Gleichheitsfunktion bekannt und gut definiert sein. –

0

Also zusammenfassend, um Zeug vergleichbar zu machen streamen Sie zuerst zu einem gemeinsamen Format, String oder Blob.

Wie behandeln Sie z.B. Lokalisierung, z.B. Formatierung von Realen? Ein reales im Vergleich zu einem String, der dasselbe Real enthält, das in einem anderen Gebietsschema erstellt wurde, schlägt fehl. Oder eine echte Zeichenfolge mit einer anderen Präzisionseinstellung.

Es klingt für mich die Definition von equal() ist das Problem, nicht das Hashing. Wenn "gleiche" Werte seriell zu String (oder Blob) serialisiert werden können, schlägt Hashing fehl.

+0

Das ist ein guter Punkt. Es gibt zwei mögliche Antworten: (a) Verwenden von invarianten Einstellungen, so dass Hash-Codes für mehrere Instanzen und Ländereinstellungen usw. zuverlässig sind, oder (b) egal, solange die Ergebnisse innerhalb eines gegebenen Laufs konsistent sind (auch wenn Einstellungen dies zulassen) ändern und brechen Sie Dinge in Randfällen). Angesichts all das, was in den Kommentaren zu meiner Frage gesagt wurde - ich wünschte, mehr dieser Kommentare wären tatsächliche Antworten - kann ich meinen Ansatz überprüfen und Arten individuell behandeln, und nicht versuchen, Delphi-ähnliche Gleichheits-Semantik zu erhalten, wenn Vergleiche etc. benötigt für Algorithmen. –

2

Es gibt eine eingebaute Spannung in Ihrer Frage zwischen der Verwendung einer Hash-Funktion und den angegebenen Anforderungen, die gegen die Eingabe des Hashs validiert werden sollen. Ich würde vorschlagen, dass wir einige Eigenschaften von Hashes im Allgemeinen berücksichtigen: Informationen gehen während des Hashing-Prozesses verloren und Hash-Kollisionen sind zu erwarten. Es ist möglich, einen perfekten Hash ohne Kollisionen zu konstruieren, aber es wäre problematisch (oder unmöglich?), Eine perfekte Hash-Funktion zu konstruieren, wenn die Domäne der Funktion irgendeine mögliche OLE-Variante ist. Auf der anderen Seite, wenn wir nicht von einem perfekten Hash sprechen, wird Ihre erste Regel verletzt.

Ich kenne nicht den größeren Kontext dessen, was Sie erreichen möchten, aber ich muss eine Ihrer Annahmen zurückdrängen: Ist eine Hash-Funktion wirklich was Sie wollen? Ihre Anforderungen können relativ einfach erfüllt werden, wenn Sie ein System entwickeln, das alle möglichen OLE-Varianten-Attribute kodiert, nicht hasht, damit sie später wieder aufgerufen und mit anderen Varianten-Images verglichen werden können.

Ihre Basisimplementierung der Konvertierung der Variante in eine Zeichenfolgendarstellung bewegt sich in diese Richtung. Wie Ihnen sicherlich bekannt ist, kann eine Variante Zeiger, Doppelzeiger und Arrays enthalten, so dass Sie eine konsistente Zeichenfolgendarstellung dieser Datentypen entwickeln müssen. Ich frage mich, ob dieser Ansatz wirklich als Hash eingestuft werden könnte. Bestehen Sie nicht nur Datenattribute?

+0

Ich schreibe eine generische Auflistungsklasse für eine Laufzeitbibliothek. Der generische Parameter könnte eine Variante sein. Perfektes Hashing ist nicht relevant. (Tatsächlich kann perfektes Hashing in kleinen Hash-Tabellen kontraproduktiv sein, indem die Kosten für eine fehlgeschlagene Hash-Suche erhöht werden.) –

Verwandte Themen