Модуль:Roman
Эту страницу предлагается объединить со страницей Модуль:RomanNumber. |
Модуль для конвертации арабских чисел в римские.
-- This module implements {{Roman}}.
local p = {}
-- This function implements the {{overline}} template.
local function overline( s )
return mw.ustring.format( '<span style="text-decoration:overline;">%s</span>', s )
end
-- Gets the Roman numerals for a given numeral table. Returns both the string of
-- numerals and the value of the number after it is finished being processed.
local function getLetters( num, t )
local ret = {}
for _, v in ipairs( t ) do
local val, letter = unpack( v )
while num >= val do
num = num - val
table.insert( ret, letter )
end
end
return table.concat( ret ), num
end
-- The main control flow of the module.
function p.convert( arg1, arg2 )
-- Get input and exit displaying nothing if the input is bad.
local num = tonumber( arg1 )
if not num or num < 1 or num == math.huge then
return
end
num = math.floor( num )
-- Return a message for numbers too big to be expressed in Roman numerals.
if num >= 5000000 then
return arg2 or 'N/A'
end
local ret = ''
-- Find the Roman numerals for the large part of numbers 5000 and bigger.
-- The if statement is not strictly necessary, but makes the algorithm
-- more efficient for smaller numbers.
if num >= 5000 then
local bigRomans = {
{ 1000000, 'M' },
{ 900000, 'CM' }, { 500000, 'D' }, { 400000, 'CD' }, { 100000, 'C' },
{ 90000, 'XC' }, { 50000, 'L' }, { 40000, 'XL' }, { 10000, 'X' },
{ 5000, 'V' }
}
local bigLetters
bigLetters, num = getLetters( num, bigRomans )
ret = overline( bigLetters )
end
-- Find the Roman numerals for numbers 4999 or less.
local smallRomans = {
{1000, "M"},
{900, "CM"}, {500, "D"}, {400, "CD"}, {100, "C"},
{90, "XC"}, {50, "L"}, {40, "XL"}, {10, "X"},
{9, "IX"}, {5, "V"}, {4, "IV"}, {1, "I"}
}
local smallLetters = getLetters( num, smallRomans )
ret = ret .. smallLetters
return ret
end
function p.main( frame )
-- If called via #invoke, use the args passed into the invoking
-- template, or the args passed to #invoke if any exist. Otherwise
-- assume args are being passed directly in from the debug console
-- or from another Lua module.
local origArgs
if frame == mw.getCurrentFrame() then
origArgs = frame:getParent().args
for k, v in pairs( frame.args ) do
origArgs = frame.args
break
end
else
origArgs = frame
end
-- Trim whitespace and remove blank arguments.
local args = {}
for k, v in pairs( origArgs ) do
if type( v ) == 'string' then
v = mw.text.trim( v )
end
if v ~= '' then
args[k] = v
end
end
return p.convert( args[ 1 ] , args[ 2 ] )
end
-- return p
-- local m = {}
-- Таблица тысяч, сотен, десятков и единиц
local digit_1000 = {[0] = "", [1] = "M", [2] = "MM", [3] = "MMM"}
local digit_100 = {[0] = "", [1] = "C", [2] = "CC", [3] = "CCC", [4] = "CD", [5] = "D", [6] = "DC", [7] = "DCC", [8] = "DCCC", [9] = "CM"}
local digit_10 = {[0] = "", [1] = "X", [2] = "XX", [3] = "XXX", [4] = "XL", [5] = "L", [6] = "LX", [7] = "LXX", [8] = "LXXC", [9] = "XC"}
local digit_1 = {[0] = "", [1] = "I", [2] = "II", [3] = "III", [4] = "IV", [5] = "V", [6] = "VI", [7] = "VII", [8] = "VIII", [9] = "IX"}
function p.toRoman(n_number)
assert((n_number >= 1) and (n_number <= 3999))
local n_1000, n_100, n_10, n_1
n_1000 = math.floor(n_number/1000)
n_number = n_number - 1000*n_1000
n_100 = math.floor(n_number/100)
n_number = n_number - 100*n_100
n_10 = math.floor(n_number/10)
n_1 = n_number - 10*n_10
return digit_1000[n_1000]..digit_100[n_100]..digit_10[n_10]..digit_1[n_1]
end;
-- Функция для шаблона Roman
-- Вызывать так: {{#invoke:Roman|roman|200}}
function p.roman(frame)
return p.toRoman(tonumber(frame.args[1]))
end
return p