The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Documentation for this module may be created at Module:Format price/doc

local p = {}
local names = {
    "million", "billion", "trillion", "quadrillion",
    "quintillion", "sextillion", "septillion", "octillion"
}

-- two_decimals: boolean, whether to forbid a 1 d.p. result, so 2 becomes "2",
--				 2.1 "2.10", and 2.123 "2.123"
function p.decimal(val, length, two_decimals)
	local precision = math.max(0, math.ceil(length - 1 - math.log10(val)))
	if two_decimals and precision == 1 then precision = 2 end
	local result = ("%%.%uf"):format(precision):format(val)
	if two_decimals then
		result = result:gsub('%.0*$', ''):gsub('(%.[0-9][0-9][0-9]-)0+$', '%1')
	else
		result = result:gsub('%.?0*$', '')
	end
	
	result = mw.text.split(result, '%.')
	result[1] = result[1]:reverse():gsub('[0-9][0-9][0-9]', '%0,'):reverse():gsub('^,','')
	return table.concat(result, '.')
end

function p.format(val, precision)
    local scale = math.floor(math.log10(val) / 3) - 1
    if scale > 0 then
        scale = math.min(scale, #names)
        val = val / math.pow(10, 3 * (1 + scale))
        return p.decimal(val, 3) .. '\194\160' .. names[scale]
    end

    if precision <= 0 then
        val = math.floor(val / math.pow(10, -precision) + 0.5)
        val = val * math.pow(10, -precision)
    end
    
    return p.decimal(val, precision + 1, true)
end

p[''] = function(frame)
	local val = tonumber(frame.args[1])
    if not val or val < 0 then
        error('[[Module:Format price|Format price]] error: cannot parse value "' .. (frame.args[1] or '') .. '"')
    end
    return p.format(val, tonumber(frame.args[2]) or 2)
end

return p