本文介绍了使用Lua中的32位按位运算比较带符号的64位数字的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Redis上使用Lua,想比较两个带符号的64位数字,这些数字存储在两个8字节/字符的字符串中.

I am using Lua on Redis and want to compare two signed 64-bit numbers, which are stored in two 8-byte/character strings.

如何使用Redis中可用的库进行比较? http://redis.io/commands/EVAL#available-libraries

How can I compare them using the libraries available in Redis? http://redis.io/commands/EVAL#available-libraries

我想知道>/<==检查.我认为这可能涉及为每个64位int提取两个32位数字,并对它们进行一些巧妙的数学运算,但是我不确定.

I'd like to know >/< and == checks. I think this probably involves pulling two 32-bit numbers for each 64-bit int, and doing some clever math on those, but I am not sure.

我有一些代码可以使这一点变得不那么抽象. a0a1b0b1都是32位数字,用于表示msb&两个64位带符号的int 64s的lsb:

I have some code to make this less abstract. a0, a1, b0, b1 are all 32 bit numbers used to represent the msb & lsb's of two 64-bit signed int 64s:

-- ...
local comp_int64s = function (a0, a1, b0, b1)
    local cmpres = 0
    -- TOOD: Real comparison
    return cmpres
end
local l, a0, a1, b0, b1
a0, l = bit.tobit(struct.unpack("I4", ARGV[1]))
a1, l = bit.tobit(struct.unpack("I4", ARGV[1], 5))
b0, l = bit.tobit(struct.unpack("I4", blob))
b1, l = bit.tobit(struct.unpack("I4", blob, 5))
print("Cmp result", comp_int64s(a0, a1, b0, b1))

添加了代码

推荐答案

我想出了一种看起来可行的方法.不过有点丑.

I came up with a method that looks like it's working. It's a little ugly though.

第一步是将前32位比较为2个恭维#MSB符号位保持不变,因此数字保持正确的关系

The first step is to compare top 32 bits as 2 compliment #’sMSB sign bit stays, so numbers keep correct relations

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

因此,除非MSB的工作结果相等,否则返回它们的结果,则需要对LSB进行检查.

So returning the result from the MSB's works unless they are equal, then the LSB's need to get checked.

我有几种情况可以建立一些模式:

I have a few cases to establish the some patterns:

-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

还有

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

MSB的正负号与b/c负数无关,它们之间的关系与正数相同.例如,无论符号位如何,总是0xff> 0xfe的lsb值.

The sign bit on MSB’s doesn’t matter b/c negative numbers have the same relationship between themselves as positive numbers. e.g regardless of sign bit, lsb values of 0xff > 0xfe, always.

如果低32位的MSB不同怎么办?

What about if the MSB on the lower 32 bits is different?

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!

因此,我们需要忽略低32位的符号位.而且由于LSB的关系是相同的,而不管其符号如何,因此只需使用最低的32位无符号在所有情况下均有效.

So we need to ignore the sign bit on the lower 32 bits. And since the relationships are the same for the LSBs regardless of sign, just usingthe lowest 32 bits unsigned works for all cases.

这意味着我要为MSB签名,而对LSB不签名-因此将LSB的I4替换为i4.还要使大端字节序成为正式文件,并在struct.unpack调用上使用>":

This means I want signed for the MSB's and unsigned for the LSBs - so chaging I4 to i4 for the LSBs. Also making big endian official and using '>' on the struct.unpack calls:

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

这篇关于使用Lua中的32位按位运算比较带符号的64位数字的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-30 15:31