Redis
 sql >> Datenbank >  >> NoSQL >> Redis

Vergleichen einer vorzeichenbehafteten 64-Bit-Zahl unter Verwendung von 32-Bit-bitweisen Operationen in Lua

Ich habe mir eine Methode ausgedacht, die so aussieht, als würde sie funktionieren. Es ist allerdings ein bisschen hässlich.

Der erste Schritt besteht darin, die oberen 32 Bits zu vergleichen, da das MSB-Vorzeichenbit von 2 Komplimenten bleibt, damit die Zahlen die richtigen Beziehungen beibehalten

-1  —> -1
0 —> 0
9223372036854775807 = 0x7fff ffff ffff ffff -> 0x7ffff ffff = 2147483647

Wenn also das Ergebnis der MSB-Arbeiten zurückgegeben wird, es sei denn, sie sind gleich, müssen die LSBs überprüft werden.

Ich habe ein paar Fälle, um einige Muster zu etablieren:

-1 = 0xffff ffff ffff ffff
-2 = 0xffff ffff ffff fffe
32 bit is:
-1 -> 0xffff ffff = -1
-2 -> 0xffff fffe = -2
-1 > -2 would be like -1 > -2 : GOOD

Und

8589934591 = 0x0000 0001 ffff ffff
8589934590 = 0x0000 0001 ffff fffe
32 bit is:
8589934591 -> ffff ffff = -1
8589934590 -> ffff fffe = -2
8589934591 > 8589934590 would be -1 > -2 : GOOD

Das Vorzeichenbit auf MSBs spielt keine Rolle, da negative Zahlen die gleiche Beziehung zueinander haben wie positive Zahlen. z. B. unabhängig vom Vorzeichenbit, LSB-Werte von 0xff> 0xfe , immer.

Was ist, wenn das MSB auf den unteren 32 Bit unterschiedlich ist?

0xff7f ffff 7fff ffff = -36,028,799,166,447,617
0xff7f ffff ffff ffff = -36,028,797,018,963,969
32 bit is:
-..799.. -> 0x7fff ffff = 2147483647
-..797.. -> 0xffff ffff = -1
-..799.. < -..797.. would be 2147483647 < -1 : BAD!

Wir müssen also das Vorzeichenbit auf den unteren 32 Bits ignorieren. Und da die Beziehungen für die LSBs unabhängig vom Vorzeichen gleich sind, funktioniert die Verwendung der niedrigsten 32 Bits ohne Vorzeichen in allen Fällen.

Das bedeutet, dass ich für die MSBs signiert und für die LSBs unsigniert haben möchte - also I4 ändern zu i4 für die LSB. Machen Sie auch Big Endian offiziell und verwenden Sie '>' bei den struct.unpack-Aufrufen:

-- ...
local comp_int64s = function (as0, au1, bs0, bu1)
    if as0 > bs0 then
        return 1
    elseif as0 < bs0 then
        return -1
    else
        -- msb's equal comparing lsbs - these are unsigned
        if au1 > bu1 then
            return 1
        elseif au1 < bu1 then
            return -1
        else
            return 0
        end
    end
end
local l, as0, au1, bs0, bu1
as0, l = bit.tobit(struct.unpack(">i4", ARGV[1]))
au1, l = bit.tobit(struct.unpack(">I4", ARGV[1], 5))
bs0, l = bit.tobit(struct.unpack(">i4", blob))
bu1, l = bit.tobit(struct.unpack(">I4", blob, 5))
print("Cmp result", comp_int64s(as0, au1, bs0, bu1))