Redis
 sql >> Base de données >  >> NoSQL >> Redis

Comparaison d'un nombre 64 bits signé à l'aide d'opérations 32 bits au niveau du bit dans Lua

J'ai trouvé une méthode qui semble fonctionner. C'est un peu moche quand même.

La première étape consiste à comparer les 32 bits supérieurs car 2 bits de signe MSB de compliment # restent, de sorte que les nombres conservent des relations correctes

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

Donc, renvoyer le résultat des travaux du MSB à moins qu'ils ne soient égaux, alors le LSB doit être vérifié.

J'ai quelques cas pour établir les quelques modèles :

-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

Et

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

Le bit de signe sur les MSB n'a pas d'importance car les nombres négatifs ont la même relation entre eux que les nombres positifs. par exemple, quel que soit le bit de signe, les valeurs lsb de 0xff> 0xfe , toujours.

Qu'en est-il si le MSB sur les 32 bits inférieurs est différent ?

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!

Nous devons donc ignorer le bit de signe sur les 32 bits inférieurs. Et puisque les relations sont les mêmes pour les LSB quel que soit le signe, il suffit d'utiliser les 32 bits non signés les plus bas pour tous les cas.

Cela signifie que je veux signé pour les MSB et non signé pour les LSB - donc changer I4 à i4 pour les LSB. Rendre également officiel le big endian et utiliser '>' sur les appels 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))