Модуль: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