2015-11-02 102 views
3

我与Redis的LUA工作,需要在现场进行了逐位逻辑运算以53位(Redis的整数部分的默认长度有序集分)Redis的LUA位溢出

但似乎我”取m运气:

127.0.0.1:6379> eval 'return bit.lshift(1, 30) ' 0 
(integer) 1073741824 
127.0.0.1:6379> eval 'return bit.lshift(1, 31) ' 0 
(integer) -2147483648 

这似乎有点*只能在30位进行操作,然后溢出(32位有符号整数)

我使用Linux 64位,Redis的编译为64位。以及。 它看起来像位库的限制:

http://bitop.luajit.org/api.html

注意,所有的位操作,返回签名的32位数字(原理)。 默认情况下这些打印为带符号的十进制数字。

在另一方面...

eval 'return math.pow(2, 53) ' 0 
(integer) 9007199254740992 

任何想法如何更好地解决这个问题?

P.S.有人会说这个逻辑移动到客户端 - 但我不能。这件作品是相当复杂的,需要紧密合作,以数据

+0

好吧,我发现这一个:HTTP://计算器。 com/a/7333595/1812225 纯粹可怕和缓慢,但看起来像redis离开我没有选择:( – let4be

+1

对于那些有兴趣的添加链接到redis问题:https://github.com/antirez/redis/issues/2843 – let4be

回答

2

这似乎位。*仅可在30位进行操作,然后溢出(32位有符号整数)

不是真的。 LuaJIT的BitOp适用于32位有符号整数。这就是为什么2^31是负数的原因。 BitOp文档解释说,之所以有符号INT32,而不是无符号的,因为架构的兼容性问题的工作是:

定义结果类型为无符号数不会 跨平台的安全。所有位操作从而定义为在带符号的32张比特数

http://bitop.luajit.org/semantics.html

进行比较的位操作,以恒定的结果时,这可能是麻烦的,有时范围返回 结果。在这种情况下,有必要使用bit.tobit()来标准化常量值。例如:

> = bit.lshift(1, 31) == 2147483648 
false 
> = bit.lshift(1, 31) == bit.tobit(2147483648) 
true 

无论如何,LuaJIT的BitOp模块仅限于32位整数。

在另一方面,如果你需要的所有位运算是lshiftrshift,有可能在普通的Lua编写这些功能:

local function lshift(n, b) 
    return n * 2^b 
end 

local function rshift(n, b) 
    return n/2^b 
end 
+0

好暗示使用简单的数学换班!允许我清除丑陋的低/高字实现,并且使代码更快;) – let4be

+0

很高兴工作:) –