2013-12-12 10 views
9

Piszę prosty skrypt Lua, aby obliczyć medianę z zestawu posortowanego (http://redis.io/commands/#sorted_set) w ramach Redis 2.8. Skrypt jest poniżejJak przekonwertować ciąg lua do 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 

Problemem jest skrypt zawsze zwraca liczbę całkowitą, gdy wynik powinien być pływak. Wynik jest nieprawidłowy.

$ 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 

prawidłowy wynik powinien być (3,1 + 3,4975) /2.0 == 3,298

Odpowiedz

9

Z documentation for EVAL:

Lua posiada pojedynczego typu liczbową numery Lua. Nie ma rozróżnienia między liczbami całkowitymi a zmiennymi. Więc zawsze konwertujemy liczby Lua na liczby całkowite, usuwając dziesiętną część liczby, jeśli taka istnieje. Jeśli chcesz zwrócić float od Lua, powinieneś zwrócić go jako ciąg, dokładnie tak, jak robi to samo Redis (patrz na przykład polecenie ZSCORE).

Dlatego należy zaktualizować skrypt więc wracają do float as a string:

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

Dzięki! "Dlatego zawsze konwertujemy liczby Lua na liczby całkowite, usuwając dziesiętną część liczby" - Czy istnieje jakikolwiek powód, który brzmi całkowicie sprzecznie z intuicją. – Adil

+0

Domyślam się, że liczby całkowite są częstszym przypadkiem użycia niż pływają w trybie redis. – Azmisov