sql >> Base de Datos >  >> NoSQL >> Redis

Comparación de números de 64 bits firmados mediante operaciones bit a bit de 32 bits en Lua

Se me ocurrió un método que parece que está funcionando. Aunque es un poco feo.

El primer paso es comparar los 32 bits principales, ya que se mantienen 2 bits de signo MSB # de complemento, de modo que los números mantengan las relaciones correctas

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

Entonces, al devolver el resultado de los trabajos de MSB a menos que sean iguales, entonces se debe verificar el LSB.

Tengo algunos casos para establecer algunos patrones:

-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

Y

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

El bit de signo en los MSB no importa porque los números negativos tienen la misma relación entre ellos que los números positivos. por ejemplo, independientemente del bit de signo, los valores lsb de 0xff> 0xfe , siempre.

¿Qué pasa si el MSB en los 32 bits inferiores es diferente?

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!

Por lo tanto, debemos ignorar el bit de signo en los 32 bits inferiores. Y dado que las relaciones son las mismas para los LSB independientemente del signo, solo usar los 32 bits más bajos sin firmar funciona para todos los casos.

Esto significa que quiero firmar para los MSB y no firmar para los LSB, así que cambie I4 a i4 para los LSB. También haciendo oficial big endian y usando '>' en las llamadas struct.unpack:

-- ...
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))