Redis
 sql >> Base de Dados >  >> NoSQL >> Redis

Comparando o número de 64 bits assinado usando operações bit a bit de 32 bits em Lua


Eu vim com um método que parece que está funcionando. Mas é um pouco feio.

O primeiro passo é comparar os 32 bits principais, pois 2 bits de sinal MSB do elogio permanecem, para que os números mantenham as relações corretas
-1  —> -1
0 —> 0
9223372036854775807 = 0x7fff ffff ffff ffff -> 0x7ffff ffff = 2147483647

Portanto, retornando o resultado dos trabalhos do MSB, a menos que sejam iguais, o LSB precisa ser verificado.

Eu tenho alguns casos para estabelecer alguns padrões:
-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

E
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

O bit de sinal nos MSBs não importa porque os números negativos têm a mesma relação entre si que os números positivos. por exemplo, independentemente do bit de sinal, valores lsb de 0xff> 0xfe , sempre.

E se o MSB nos 32 bits inferiores for 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!

Portanto, precisamos ignorar o bit de sinal nos 32 bits inferiores. E como as relações são as mesmas para os LSBs, independentemente do sinal, basta usar os 32 bits mais baixos sem sinal para todos os casos.

Isso significa que eu quero assinado para os MSBs e não assinado para os LSBs - então alterando I4 para i4 para os LSB. Também oficializando o big endian e usando '>' nas chamadas 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))