2013-12-12 25 views
9

Sto scrivendo un semplice script Lua per calcolare una mediana da un set ordinato (http://redis.io/commands/#sorted_set) all'interno di Redis 2.8. Lo script è sottoCome convertire una stringa Lua in float

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 

Il problema è lo script restituisce sempre un numero intero, quando il risultato dovrebbe essere un galleggiante. Il risultato è sbagliato

$ 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 

Il risultato corretto dovrebbe essere (3,1 + 3,4975) /2.0 == 3,298

risposta

9

Dal documentation for EVAL:

Lua prevede un unico tipo numerico, numeri Lua. Non c'è distinzione tra interi e float. Quindi convertiamo sempre i numeri Lua in risposte intere, rimuovendo la parte decimale del numero, se presente. Se si desidera restituire un float da Lua, si dovrebbe restituirlo come una stringa, esattamente come fa Redis stesso (si veda ad esempio il comando ZSCORE).

Pertanto, è necessario aggiornare il vostro script in modo si restituisce il float as a string:

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

Grazie! "Quindi convertiamo sempre i numeri Lua in risposte intere, rimuovendo la parte decimale del numero" - C'è qualche ragione per farlo, sembra completamente contro-intuitivo. – Adil

+0

Suppongo che gli interi siano il caso d'uso più comune rispetto a quelli in rosso. – Azmisov

Problemi correlati