如何将Lua字符串转换为浮点数

16

我正在编写一个简单的Lua脚本,从Redis 2.8中的Sorted Set (http://redis.io/commands/#sorted_set)计算中位数。以下是脚本:

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

2个回答

17
根据EVAL命令的文档
Lua只有一种数值类型,即Lua数字。在Lua中没有整数和浮点数之分。因此,我们总是将Lua数字转换为整数回复,并删除数字的小数部分(如果有)。如果你想从Lua返回一个浮点数,你应该将它作为字符串返回,就像Redis自身做的一样(例如参见ZSCORE命令)。
因此,您应该更新脚本,以便将浮点数作为字符串返回:
return tostring((tonumber(vals[1]) + tonumber(vals[2]))/2.0)

感谢!“因此,我们总是将Lua数字转换为整数回复,删除数字的小数部分”-是否有任何原因,听起来完全不符合直觉。 - Adil
我猜在Redis中,整数比浮点数更常见。 - Azmisov

0

抱歉,我无法解释这个问题。这是我在编写脚本时意外遇到的。

function int2float(integer)
  return integer + 0.0
end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接