2 Stimmen

Warum gibt base_convert in PHP ein anderes Ergebnis als die gleiche MYSQL-Funktion?

Ich habe eine PHP-Funktion wie folgt zusammengestellt:

function keyword_hash($keyword) {
  return base_convert(substr(md5($keyword), -16), 16, 10);
}

Das Ziel dieser Funktion ist es, einen numerischen Hash-Wert zu erzeugen, den ich in einer Datenbank speichern und für einen Lookup verwenden kann (anstatt zu versuchen, eine Schlüsselwortspalte zu indizieren).

Das Äquivalent dieser Funktion in MySQL ist wie folgt:

SELECT CONV(RIGHT(MD5('some keyword'), 16), 16, 10);

Ich habe überprüft, dass der MD5-String der gleiche ist und dass die substr()-Funktion den Wert, den ich von RIGHT() in der MySQL-Abfrage zurückbekomme, entspricht. Allerdings erhalte ich beim Ausführen von CONV() einen anderen Wert als bei base_convert() generiert wird.

Zum Beispiel erzeugt keyword_hash("some keyword") einen Wert von 10923672322315740844. Jedoch erzeugt SELECT CONV(RIGHT(MD5('some keyword'), 16), 16, 10) 10923672322315740475, wobei die letzten drei Zahlen unterschiedlich sind.

Was fehlt mir hier? Sollten sie nicht den gleichen Wert produzieren?

3voto

MarcDefiant Punkte 6301

Ich habe mir die PHP-Manual-Seite für base_convert() angesehen. Dort gibt es folgende Warnung:

base_convert() kann bei großen Zahlen aufgrund von Eigenschaften des internen Typs "double" oder "float" an Präzision verlieren. Bitte sehen Sie sich den Abschnitt über Gleitkommazahlen im Handbuch für spezifischere Informationen und Beschränkungen an.

Später in den Kommentaren hat jemand bereits eine Lösung für dieses Problem gefunden (danke @CraigSefton):

function str_baseconvert($str, $frombase=10, $tobase=36) { 
    $str = trim($str); 
    if (intval($frombase) != 10) { 
        $len = strlen($str); 
        $q = 0; 
        for ($i=0; $i<$len; $i++) { 
            $r = base_convert($str[$i], $frombase, 10); 
            $q = bcadd(bcmul($q, $frombase), $r); 
        } 
    } 
    else $q = $str; 

    if (intval($tobase) != 10) { 
        $s = ''; 
        while (bccomp($q, '0', 0) > 0) { 
            $r = intval(bcmod($q, $tobase)); 
            $s = base_convert($r, 10, $tobase) . $s; 
            $q = bcdiv($q, $tobase, 0); 
        } 
    } 
    else $s = $q; 

    return $s; 
}

Diese Funktion verwendet die bc math-Bibliothek, die aufgrund der Verwendung von Zeichenfolgen zur Speicherung der Zahlen anstelle von Ganzzahlen/Fließkommazahlen etc. beliebige Präzisionsmathematik unterstützt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X