<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Was genau macht dieser code?]]></title><description><![CDATA[<p>Hallo,</p>
<p>vor längerer Zeit hat jemand aus dem Forum hier eine Hash-Funktion für double werte geschrieben. Sie funktioniert prima. Was sie tut: aus einem double einen eindeutigen hash-wert zurückzugeben.</p>
<p>Nur verstehe ich absolut nicht wie intern diese 2 Zeilen arbeiten.<br />
Ich bräuchte wirklich jemanden der GENAU erklärt was mit welchen BIts passiert und vor allem warum. Ich versuche es unten von selbst damit ihr seht wie dumm ich bis jetzt bin <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
<pre><code class="language-cpp">typedef unsigned int U_Int32;                  
typedef unsigned long long U_Int64; 

inline U_Int32 
Hash::hash_double(double x)
{ 
    U_Int64* p = reinterpret_cast&lt; U_Int64* &gt; (&amp;x); 
    return *p ^ (*p &gt;&gt; 32); 
}
</code></pre>
<p>Mein Versuch:<br />
x hat 64 Bit und wird übergeben,<br />
wir erzeugen einen pointer p der auch 64 Bit hat und der auf die Adresse von x zeigt. also dorthin zeigt er wo x was trägt sozusgaen.<br />
Jetzt nehmen wir den Inhalt von x (weil ja p draufzeigt) der 64 BIt hat, shiften ihn einmal um 32 Bit nach rechts so das in den ersten 32 Bits NUllen erzeugt werden. Jetzt machen wir ein XOR zwischen dem kompletten wert aus x und diesen geshifteten und geben nur die unteren 32 Bits zurück????????</p>
<p><img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f62e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_open_mouth"
      title=":open_mouth:"
      alt="😮"
    /></p>
<p>Hilfe bitte</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/185754/was-genau-macht-dieser-code</link><generator>RSS for Node</generator><lastBuildDate>Thu, 24 Sep 2026 06:02:43 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/185754.rss" rel="self" type="application/rss+xml"/><pubDate>Sat, 30 Jun 2007 18:15:45 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Was genau macht dieser code? on Sat, 30 Jun 2007 18:15:45 GMT]]></title><description><![CDATA[<p>Hallo,</p>
<p>vor längerer Zeit hat jemand aus dem Forum hier eine Hash-Funktion für double werte geschrieben. Sie funktioniert prima. Was sie tut: aus einem double einen eindeutigen hash-wert zurückzugeben.</p>
<p>Nur verstehe ich absolut nicht wie intern diese 2 Zeilen arbeiten.<br />
Ich bräuchte wirklich jemanden der GENAU erklärt was mit welchen BIts passiert und vor allem warum. Ich versuche es unten von selbst damit ihr seht wie dumm ich bis jetzt bin <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
<pre><code class="language-cpp">typedef unsigned int U_Int32;                  
typedef unsigned long long U_Int64; 

inline U_Int32 
Hash::hash_double(double x)
{ 
    U_Int64* p = reinterpret_cast&lt; U_Int64* &gt; (&amp;x); 
    return *p ^ (*p &gt;&gt; 32); 
}
</code></pre>
<p>Mein Versuch:<br />
x hat 64 Bit und wird übergeben,<br />
wir erzeugen einen pointer p der auch 64 Bit hat und der auf die Adresse von x zeigt. also dorthin zeigt er wo x was trägt sozusgaen.<br />
Jetzt nehmen wir den Inhalt von x (weil ja p draufzeigt) der 64 BIt hat, shiften ihn einmal um 32 Bit nach rechts so das in den ersten 32 Bits NUllen erzeugt werden. Jetzt machen wir ein XOR zwischen dem kompletten wert aus x und diesen geshifteten und geben nur die unteren 32 Bits zurück????????</p>
<p><img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f62e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_open_mouth"
      title=":open_mouth:"
      alt="😮"
    /></p>
<p>Hilfe bitte</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1315821</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1315821</guid><dc:creator><![CDATA[Mati]]></dc:creator><pubDate>Sat, 30 Jun 2007 18:15:45 GMT</pubDate></item><item><title><![CDATA[Reply to Was genau macht dieser code? on Sat, 30 Jun 2007 18:33:20 GMT]]></title><description><![CDATA[<p>hola</p>
<p>Mati schrieb:</p>
<blockquote>
<p>wir erzeugen einen pointer p der auch 64 Bit hat ...</p>
</blockquote>
<p>noe stimmt so nicht ganz. ein pointer wird hochstwahrscheinlich 32 bit breit sein, aber er zeigt auf einen 64-bit breiten integer. zu mindest nach dem reinterpret_cast.<br />
der schreiberling kann nun mit (double)x rechnen wie mit einem 64 bit breiten integer.<br />
ausserdem werden nicht in den ersten 32 bits auf 0 gesetzt sondern die letzten 32.<br />
warum er jedoch genau diesen algortihmus verwendet vermag ich dir leider auch nicht zu sagen.<br />
[edit] die funktion gibt den wert zurueck den die ersten 32 bit xor den 2ten 32 bit ergibt [/edit]</p>
<p>Meep Meep</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1315827</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1315827</guid><dc:creator><![CDATA[Meep Meep]]></dc:creator><pubDate>Sat, 30 Jun 2007 18:33:20 GMT</pubDate></item><item><title><![CDATA[Reply to Was genau macht dieser code? on Sun, 01 Jul 2007 18:47:34 GMT]]></title><description><![CDATA[<p>Hallo zusammen,</p>
<p>es handelt sich bei der Funktion um eine Routine, die zu einer Gleitkommazahl einen Hashwert bildet.</p>
<p>Zuerst wollen wir uns anschauen, wie viel Speicher die vorkommenden Datentypen benötigen...</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
using namespace std;
int main() {
    cout &lt;&lt; &quot;u int &quot; &lt;&lt; sizeof(unsigned int) &lt;&lt; endl;
    cout &lt;&lt; &quot;u long long &quot; &lt;&lt; sizeof(unsigned long long) &lt;&lt; endl;
    cout &lt;&lt; &quot;double &quot; &lt;&lt; sizeof(double) &lt;&lt; endl;
}
</code></pre>
<blockquote>
<p>u int 4<br />
u long long 8<br />
double 8</p>
</blockquote>
<p>Wir halten also fest: Ein positiver, ganzzahliger Wert benötigt 4 (der Einfachheit halber) &quot;Einheiten&quot;. Ein Wert vom Typ unsigned long long benötigt das Doppelte, nämlich 8 Einheiten - Das ist genausoviel Speicher wie eine Gleitkommazahl (double) in Anspruch nimmt.</p>
<p>Der Funktion hash_double wird eine Gleitkommazahl x übergeben. Diese wird als Ganzzahl vom Typ unsigned long long aufgefasst (*p). Dies wird als Zeiger p auf die lokale Variable x umgesetzt.</p>
<p>Nun wird der Shift-Operator auf den Wert des dereferenzierten Zeiger p angewandt und anschließend mit *p verknüpft. Relevant ist an dieser Stelle nur der &quot;zweite&quot; Teil (die letzte Hälfte der Bits) des Wertes, da die Routine hash_double eine 32Bit-Ganzzahl zurückgibt (es findet also implizit eine Typumwandlung statt).</p>
<p>Zusammenfassend kann man sagen: Die Funktion hash_double fasst eine 64 Bit Gleitkommazahl als Ganzzahl auf und Verknüpft die erste Hälfte der Bits via XOR mit der zweiten Hälfte der Bits. Das Ergebnis der Bitoperation wird als 32 Bit Ganzzahl zurückgegeben.</p>
<p>Zahlen aus einer Quellmenge werden Hashwerte zugeordnet, welche deutlich weniger Speicher in Anspruch nehmen und möglichst eindeutig sind.</p>
<p><a href="http://de.wikipedia.org/wiki/Hash" rel="nofollow">http://de.wikipedia.org/wiki/Hash</a> sollte weitere Informationen liefern.</p>
<p>Grüße Martin</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1316339</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1316339</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Sun, 01 Jul 2007 18:47:34 GMT</pubDate></item><item><title><![CDATA[Reply to Was genau macht dieser code? on Sun, 01 Jul 2007 22:03:41 GMT]]></title><description><![CDATA[<p>lucky_tux schrieb:</p>
<blockquote>
<p>&quot;Einheiten&quot;</p>
</blockquote>
<p>=Bytes.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1316504</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1316504</guid><dc:creator><![CDATA[queer_boy]]></dc:creator><pubDate>Sun, 01 Jul 2007 22:03:41 GMT</pubDate></item><item><title><![CDATA[Reply to Was genau macht dieser code? on Sun, 01 Jul 2007 22:22:59 GMT]]></title><description><![CDATA[<p>Mati schrieb:</p>
<blockquote>
<p>vor längerer Zeit hat jemand aus dem Forum hier eine Hash-Funktion für double werte geschrieben. Sie funktioniert prima. Was sie tut: aus einem double einen eindeutigen hash-wert zurückzugeben.</p>
</blockquote>
<p>Einen Hash-Wert. Das &quot;eindeutig&quot; ist hier überflüssig bzw. falsch, je nachdem, wie man es versteht.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1316514</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1316514</guid><dc:creator><![CDATA[Bashar]]></dc:creator><pubDate>Sun, 01 Jul 2007 22:22:59 GMT</pubDate></item><item><title><![CDATA[Reply to Was genau macht dieser code? on Mon, 02 Jul 2007 14:52:59 GMT]]></title><description><![CDATA[<p>Danke euch vielmals - vor allem auch lucky_tux für die ausführliche Antwort!</p>
<p>Mir ist schon vieles klarer.</p>
<p>Aufgerufen wird die Funktion ja so:</p>
<pre><code class="language-cpp">U_Int32 
Hash::compute_key(const double* vec, 
                  size_t size) const
{                    
    //The mix value is necessary because of the zero elements. 
    //without v1 = 0.0 0.0 1.0 and v2 = 0.0 0.0 0.0 1.0 would
    //produce the same key
    U_Int32 ret = 0;
    U_Int32 mix = hash_double(0.13);
    while(size--)
    {
        ret = (ret * 31) + mix + hash_double(*vec);
        vec++;
    } 
    return ret;
}
</code></pre>
<p>Wäre es nicht sinnvoller gewesen eher gleich nen 64 Bit Rückgabewert zu generieren anstatt nur die gemixten 32 Bit zurückzugeben aus der Funktion? Oder ist das in diesem Fall egal?<br />
Man könnte doch trotzdem die Bits mixen und dann nen 64 Bit Wert als Hashwert zurückgeben oder? Wäre das nicht besser?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1316947</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1316947</guid><dc:creator><![CDATA[Mati]]></dc:creator><pubDate>Mon, 02 Jul 2007 14:52:59 GMT</pubDate></item><item><title><![CDATA[Reply to Was genau macht dieser code? on Mon, 02 Jul 2007 23:26:11 GMT]]></title><description><![CDATA[<blockquote>
<p>Wäre es nicht sinnvoller gewesen eher gleich nen 64 Bit Rückgabewert zu generieren anstatt nur die gemixten 32 Bit zurückzugeben aus der Funktion? Oder ist das in diesem Fall egal?<br />
Man könnte doch trotzdem die Bits mixen und dann nen 64 Bit Wert als Hashwert zurückgeben oder? Wäre das nicht besser?</p>
</blockquote>
<p>Wir müssen uns vor Augen halten, wozu wir eigentlich Container in Kombination mit Hashwerten verwenden...</p>
<p>Hashwerte werden generiert um Datenbestände schnell zu verwalten. Zum beispiel können in einem Container der Gebrauch von Hash-Funktionen macht schnell Datenelemente miteinander verglichen werden oder nach der Größe geordnet werden o.Ä..</p>
<p>Um nun zur Frage zurückzukommen ein Beispiel: Angenommen wir haben 10 große Texte à 20MB. Nun wollen wir alle gleichen Texte rausfinden. Anstatt nun die Texte von jeweils 20MB miteinander zu vergleichen, erstellen wir zu jedem Text einen Hashwert von 2MB und vergleichen diese generierten Werte untereinander - somit sparen wir Zeit und das Programm ist deutlich performanter.<br />
Wenn den Hashwert nun ebenfalls 20MB betragen würde, so könnten wir auch direkt die Texte vergleichen und hätten die Zeit gespart, die für das Erzeugen der Hashwerte anfällt.</p>
<p>Hashwerte finden gerade bei vielen und großen Datenbeständen wie z.B. in Datenbanken häufig Einsatz. Wenn Hashwerte gebildet werden, so ist dies zumeist immer mit einem Informationsverlust verbunden, weswegen die Wahl der Hash-Funktion entscheiden ist.</p>
<p>Grüße Martin</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1317226</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1317226</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Mon, 02 Jul 2007 23:26:11 GMT</pubDate></item><item><title><![CDATA[Reply to Was genau macht dieser code? on Tue, 03 Jul 2007 13:00:55 GMT]]></title><description><![CDATA[<p>Hallo Martin,</p>
<p>danke für Deine genauen Antworten - alles sehr interessant.</p>
<p>Leider verstehe ich nicht ganz Deine Antwort auf meine Frage. Meinst Du vielleicht dass die Schlüssel deshalb so gewählt wurden (32 Bit) weil wir da mit einer komprimierten Datenmenge arbeiten? ALso sprich da wir ja so schneller suchen können als gleich die gesamten Elemente miteinander zu vergleichen die z.B 64 Bit groß sind?</p>
<p>Danke für Deine Antwort</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1317496</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1317496</guid><dc:creator><![CDATA[Mati]]></dc:creator><pubDate>Tue, 03 Jul 2007 13:00:55 GMT</pubDate></item><item><title><![CDATA[Reply to Was genau macht dieser code? on Tue, 03 Jul 2007 13:25:55 GMT]]></title><description><![CDATA[<p>Hashfunktionen werden i.d.R. geschrieben, um eine Speicheradresse zu berechnen, mit der man einen schnellen Zugriff auf ein gespeichertes Objekt hat.</p>
<p>Man kann hier also ziemlich sicher annehmen, das 32 Bit für eine vollständige Adressierung aller Objekte ausreichen.<br />
Ein 64 Bit Wert und der damit einhergehende reservierte Speicherplatz wäre dann also überdimensioniert.<br />
MfG</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1317519</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1317519</guid><dc:creator><![CDATA[proggingmania]]></dc:creator><pubDate>Tue, 03 Jul 2007 13:25:55 GMT</pubDate></item><item><title><![CDATA[Reply to Was genau macht dieser code? on Tue, 03 Jul 2007 15:40:59 GMT]]></title><description><![CDATA[<p>Hashcodes werden oft mal verwendet um Vergleiche zu beschleunigen, richtig.</p>
<p>Hashcodes können aber genauso für einen Hashtable verwendet werden, und da kommts nicht darauf an dass der Hashcode schneller zu vergleichen geht, sondern dass man aus &quot;was auch immer&quot; (müssen ja keine doubles sein) einen Integerwert bekommt.<br />
Diesen Integerwert bildet man dann (üblicherweise einfach mit Modulo) auf ein Fenster [0-N) ab, wobei N die grösse des Hashtables ist.<br />
An diesem Index im Table legt man dann das zum Hashcode gehörende Objekt ab.</p>
<p>Natürlich kann es dabei zu Kollisionen kommen, da gibt es dann verschiedene Verfahren das &quot;aufzulösen&quot; (die einfachste ist dass die Elemente des Tables einfach Listen von Werten sind, man kann also zu jedem Index mehrere Werte ablegen).</p>
<p>Wenn man dann einen bestimmten Wert in so einem Hashtable suchen möchte muss man nur den Hashcode bilden, den auf das Fenster abbilden, an der Stelle im Table nachgucken und fertig. (Das &quot;Nachgucken&quot; geht dabei üblicherweise sehr schnell, denn wenn der Hashtable gross genug gewählt ist kommt es sehr selten vor dass zu einem Index mehr als 2 oder 3 Werte abgelegt sind.)</p>
<p>Man gewinnt also nicht dadurch Geschwindigkeit dass der Hashcode kleiner und schneller zu vergleichen ist als der Originalwert, sondern dadurch dass man im Idealfall bloss einen einzigen Vergleich durchführen muss - egal wieviele Elemente der Hashtable enthält.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1317598</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1317598</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Tue, 03 Jul 2007 15:40:59 GMT</pubDate></item></channel></rss>