## average

in lua

### Source Code

``````-- Various average (means) algorithms implementation
-- See: http://en.wikipedia.org/wiki/Average

-- Returns the sum of a sequence of values
local function sum(x)
local s = 0
for _, v in ipairs(x) do s = s + v end
return s
end

-- Calculates the arithmetic mean of a set of values
-- x       : an array of values
-- returns : the arithmetic mean
local function arithmetic_mean(x)
return (sum(x) / #x)
end

-- Calculates the geometric mean of a set of values
-- x       : an array of values
-- returns : the geometric mean
local function geometric_mean(x)
local prod = 1
for _, v in ipairs(x) do prod = prod * v end
return (prod ^ (1 / #x))
end

-- Calculates the harmonic mean of a set of values
-- x       : an array of values
-- returns : the harmonic mean
local function harmonic_mean(x)
local s = 0
for _, v in ipairs(x) do s = s + (1 / v) end
return (#x / s)
end

-- Calculates the quadratic mean of a set of values
-- x       : an array of values
-- returns : the quadratic mean
local ssquares = 0
for _, v in ipairs(x) do ssquares = ssquares + (v * v) end
return math.sqrt((1 / #x) * ssquares)
end

-- Calculates the generalized mean (to a specified power p) of a set of values
-- x       : an array of values
-- p       : a power
-- returns : the generalized mean
local function generalized_mean(x, p)
local sump = 0
for _, v in ipairs(x) do sump = sump + (v ^ p) end
return ((1 / #x) * sump) ^ (1 / p)
end

-- Calculates the weighted mean of a set of values
-- x       : an array of values
-- w       : an array of weights for each value in x
-- returns : the weighted mean
local function weighted_mean(x, w)
local sump = 0
for i, v in ipairs (x) do sump = sump + (v * w[i]) end
return sump / sum(w)
end

-- Calculates the midrange mean of a set of values
-- x       : an array of values
-- returns : the midrange mean
local function midrange_mean(x)
local sump = 0
return 0.5 * (math.min(unpack(x)) + math.max(unpack(x)))
end

-- Calculates the energetic mean of a set of values
-- x       : an array of values
-- returns : the energetic mean
local function energetic_mean(x)
local s = 0
for _,v in ipairs(x) do s = s + (10 ^ (v / 10)) end
return 10 * math.log10((1 / #x) * s)
end

return {
arithmetic     = arithmetic_mean,
geometric      = geometric_mean,
harmonic       = harmonic_mean,
generalized    = generalized_mean,
weighted       = weighted_mean,
midrange       = midrange_mean,
energetic = energetic_mean,
}``````
``````-- Tests for average.lua
local mean = require 'average'

local total, pass = 0, 0

local function dec(str, len)
return #str < len
and str .. (('.'):rep(len-#str))
or str:sub(1,len)
end

local function run(message, f)
total = total + 1
local ok, err = pcall(f)
if ok then pass = pass + 1 end
local status = ok and 'PASSED' or 'FAILED'
print(('%02d. %68s: %s'):format(total, dec(message,68), status))
end

local function fuzzyEqual(a, b, eps) return math.abs(a - b) < eps end
local x = {1, 2, 3, 4, 5}

run('Arithmetic mean', function()
assert(mean.arithmetic(x) == 3)
end)

run('Geometric mean', function()
assert(fuzzyEqual(mean.geometric(x), 2.60517108,1e-8))
end)

run('Harmonic mean', function()
assert(fuzzyEqual(mean.harmonic(x), 2.18978102,1e-8))
end)

end)

run('Generalized mean', function()
assert(fuzzyEqual(mean.generalized(x,1), mean.arithmetic(x),1e-8))
assert(fuzzyEqual(mean.generalized(x,-1), mean.harmonic(x),1e-8))
end)

run('Weighted mean', function()
local w = { 0.1, 0.2, 0.2, 0.3, 0.2}
assert(mean.weighted(x, w) == 3.3)
end)

run('Midrange mean', function()
assert(mean.midrange(x) == 3)
end)

run('Energetic mean', function()
assert(fuzzyEqual(mean.energetic(x), 3.22766781,1e-8))
end)

print(('-'):rep(80))
print(('Total : %02d: Pass: %02d - Failed : %02d - Success: %.2f %%')
:format(total, pass, total-pass, (pass*100/total)))
``````