2013-12-12 36 views
9

我正在编写一个简单的Lua脚本来计算Redis 2.8中Sorted Set(http://redis.io/commands/#sorted_set)的中位数。脚本低于如何将Lua字符串转换为浮点数

local cnt = redis.call("ZCARD", KEYS[1]) 

if cnt > 0 then 
     if cnt%2 > 0 then 
       local mid = math.floor(cnt/2) 
       return redis.call("ZRANGE", KEYS[1], mid, mid) 
     else 
       local mid = math.floor(cnt/2) 
       local vals = redis.call("ZRANGE", KEYS[1], mid-1, mid) 
       return (tonumber(vals[1]) + tonumber(vals[2]))/2.0 
     end 
else 
     return nil 
end 

问题是脚本总是返回一个整数,当结果应该是一个浮点数时。结果是错误的。

$ redis-cli zrange floats 0 100 
1) "1.1" 
2) "2.1" 
3) "3.1" 
4) "3.4975" 
5) "42.63" 
6) "4.1" 

$ redis-cli EVAL "$(cat median.lua)" 1 floats 
(integer) 3 

正确的结果应为(3.1 + 3.4975)/2.0 == 3.298

回答

9

documentation for EVAL

lua有一个单一的数值类型,Lua的号码。整数和浮点数之间没有区别。所以我们总是将Lua数字转换为整数回复,如果有的话删除数字的小数部分。 如果你想从Lua返回一个浮点数,你应该像字符串那样返回它,就像Redis本身一样(参见例如ZSCORE命令)。

因此,应使你返回float as a string更新脚本:

return tostring((tonumber(vals[1]) + tonumber(vals[2]))/2.0) 
+0

谢谢! “所以我们总是将Lua数字转换为整数回复,删除数字的小数部分” - 这是否有任何理由,听起来完全违反直觉。 – Adil

+0

我猜整数是比redis中的浮点数更常见的用例。 – Azmisov