Jump to content
Toggle menu
  • 8 articles
  • 75 files
  • 7 users
  • 37.8K edits
Neodyland Wiki
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.
Revision as of 08:45, 9 January 2015 by commons>RP88 (Add support for roman to arabic conversion. Assorted formatting and style cleanup.)
Module documentation[ view · edit · history · purge ]
This documentation is transcluded from Module:Roman/doc.

Summary

This module contains functions for working with Roman numerals. Currently used by:

Using this module from templates

Numeral

This function converts an Arabic numeral into a Roman numeral. It works for values between 0 (N) and 4999999999 (M̿M̿M̿M̿C̿M̿X̿C̿I̿X̿C̅M̅X̅C̅I̅X̅CMXCIX): this includes the whole range of unsigned 32-bit integers. The output string no longer contain HTML tags. If needed you can add external CSS formatting using a serif font family, or a small-caps font variant. Arabic numeral zero is output as 'N' (for Classical Latin adverbs "Nec" or "non"), like in standard CLDR Data.

If the input does not look like it contains a number or the number is outside of the supported range, an error message is returned. If an error message is returned, the error message will contain code to categorize pages into Category:Errors reported by Module Roman.

Usage:

{{#invoke:Roman|Numeral|''value''}}

Example: {{#invoke:Roman|Numeral|8}} produces VIII.

Arabic

This function converts a Roman numeral into an Arabic numeral. It works for values between 0 (N) and 4999999999 (M̿M̿M̿M̿C̿M̿X̿C̿I̿X̿C̅M̅X̅C̅I̅X̅CMXCIX): this includes the whole range of unsigned 32-bit integers.

If the input does not look like it contains a number or the number is outside of the supported range, an error message is returned. If an error message is returned, the error message will contain code to categorize pages into Category:Errors reported by Module Roman.

Usage:

{{#invoke:Roman|Arabic|''value''}}

Example: {{#invoke:Roman|Arabic|viii}} produces Script error: The function "Arabic" does not exist..

Using this module from Lua code

In order to use the functions in this module from another Lua module you first have to import this module.

Example:

local roman = require('Module:Roman')

_Numeral

This function converts an Arabic numeral into a Roman numeral. It works for values between 0 and 4999999. The output string may contain HTML tags. Arabic numeral zero is output as an empty string. If the input does not look like it contains a number or the number is outside of the supported range an error message is returned. If an error message is returned, the error message will contain code to categorize pages into Category:Errors reported by Module Roman.

Usage:

roman_value = roman._Numeral(value)

isRoman

Tests if the input is a valid Roman numeral. Returns true if so, false if not. For the purposes of this function, the empty string is not a valid Roman numeral.

Usage:

if roman.isRoman(roman_value) then

toArabic

This function converts a Roman numeral into an Arabic numeral. It works for values between 0 and 4999999999. The string 'N' is converted to zero. If the input is not a valid Roman numeral this function attempts to parse it as an Arabic number and returns nil if it also fails.

Usage:

arabic_value = roman.toArabic(value)
--[[  
 
This module converts Arabic numerals into Roman numerals.  It currently works for any 
whole number between 0 and 4999999.
 
Please do not modify this code without applying the changes first at Module:Roman/sandbox and testing 
at Module:Roman/sandbox/testcases and Module talk:Roman/sandbox/testcases.
 
Authors and maintainers:
* User:RP88
 
]]

local p = {}
 
-- =======================================
-- === Public Functions ==================
-- =======================================

--[[
Numeral
 
This function converts an Arabic numeral into a Roman numeral.  It works for values between 
0 and 4999999.  The output string may contain HTML tags.  Arabic numeral zero is output as
an empty string.
 
Usage:
{{#invoke:Roman|Numeral|<value>}}
{{#invoke:Roman|Numeral}} - uses the caller's parameters

Parameters
   1: Value to convert into a Roman numeral. Must be at least 0 and less than 5,000,000. 
 
Error Handling:
   If the input does not look like it contains a number or the number is outside of the
   supported range an error message is returned.
]]
function p.Numeral(frame)
	-- if no argument provided than check parent template/module args
	local args = frame.args
	if args[1]==nil then
		args = frame:getParent().args 
	end
		
	return p._Numeral(args[1])
end


--[[
_Numeral

This function returns a string containing the input value formatted as a Roman numeral.  It works for values between 
0 and 4999999. The output string may contain HTML tags.

Parameters
   input: integer or string containing value to convert into a Roman numeral

Error Handling:
   If the input does not look like it contains a number or the number is outside of the
   supported range an error message is returned.
]]
function p._Numeral(input)
	local output = ''

	if input then
		local value = tonumber(input)
		if value and (value >= 0) and (value < 5000000) then
			output = convertArabicToRomanHTML( value )
		else
			output = outputError( "unsupported value" )
		end
	else
		output = outputError( "missing value" )
	end
	
	return output
end


--[[
isRoman

Tests if the input is a valid Roman numeral.  Returns true if so, false if not.  For the
purposes of this function, the empty string is not a Roman numeral.

Parameters
   s: string to test if it is a valid Roman numeral

Error Handling:
   If the input does not look like it contains a Roman numeral or the number is outside of the
   supported range false is returned.
]]
function p.isRoman(s)
	return s and (s ~= '') and (p.toArabic(s) ~= 0)
end


--[[
toArabic

This function converts a Roman numeral into an Arabic numeral.  It works for values between 
0 and 4999.  The empty string is converted to zero.

Parameters
   roman: string containing value to convert into an Arabic numeral

Error Handling:
   If the input does not look like it contains a Roman numeral or the number is outside of the
   supported range this function return zero.
]]
function p.toArabic(roman)
	local result = 0

	if roman and (roman ~= '') then
		result = convertRomanHTMLToArabic(mw.ustring.lower(roman))
	end

	return result
end


-- =======================================
-- === Private Functions =================
-- =======================================

local overline_start = '<span style="text-decoration:overline;">'
local overline_end = '</span>'

--[[
This function returns a string containing the input value formatted as a Roman numeral.  It works for values between 
0 and 4999999. The output string may contain HTML tags.
]]
function convertArabicToRomanHTML(value)
	local output = ''
	
	if (value < 5000) then
		output = convertArabicToRoman(value)
	else
		local low_value
		if (math.floor(value) % 5000) >= 4000 then
			low_value = math.floor(value) % 1000;
		else
			low_value = math.floor(value) % 5000;
		end
		local high_value = math.floor((value - low_value) / 1000)
		
		local low_roman = convertArabicToRoman(low_value)
		local high_roman = convertArabicToRoman(high_value)
		
		output = overline_start .. high_roman .. overline_end .. low_roman
	end
	
	return output
end


--[[
This function returns a string containing the input value formatted as a Roman numeral.  It works for values between 
0 and 4999. The output string will be a simple alphanumeric string.
]]
function convertArabicToRoman(value)
	local thousands = {'', 'M', 'MM', 'MMM', 'MMMM'}
	local hundreds = {'', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM'}
	local tens = {'', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC'}
	local ones = {'', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX'}
	local index
	local result = ''
	
	if ((value >= 0) and (value < 5000)) then
		index = (math.floor(value / 1000) % 5) + 1
		result = result .. thousands[index]
		index = (math.floor(value / 100) % 10) + 1
		result = result .. hundreds[index]
		index = (math.floor(value / 10) % 10) + 1
		result = result .. tens[index]
		index = (math.floor(value) % 10) + 1
		result = result .. ones[index]
	end
	
	return result
end


--[[
This function converts a string containing a Roman numeral to an integer.  It works for values between 
0 and 4999999. The input string may contain HTML tags.
]]
function convertRomanHTMLToArabic(roman)
	local result = 0
	
	if mw.ustring.find(roman, "^[mdclxvi]+$") ~= nil then
		result = convertRomanToArabic(roman)
	else
		local overline_start_len = mw.ustring.len(overline_start)
		if mw.ustring.sub(roman, 1, overline_start_len) == overline_start then
			local end_tag_start, end_tag_end = mw.ustring.find(roman, overline_end, overline_start_len, true)
			if end_tag_start ~= nil then
				local roman_high = mw.ustring.sub(roman, overline_start_len + 1, end_tag_start - 1)
				local roman_low = mw.ustring.sub(roman, end_tag_end + 1, mw.ustring.len(roman)) or ''
		
				if (mw.ustring.find(roman_high, "^[mdclxvi]+$") ~= nil) and (mw.ustring.find(roman_low, "^[mdclxvi]*$") ~= nil) then
					result = convertRomanToArabic(roman_high) * 1000 + convertRomanToArabic(roman_low)
				end
			end
		end
	end
	
	return result
end


--[[
This function converts a string containing a Roman numeral to an integer.  It works for values between 
0 and 4999.
]]
function convertRomanToArabic(roman)
	local romanDecimals = {m = 1000, d = 500, c = 100, l = 50, x = 10, v = 5, i = 1}
	local prevRomanDecimal = 0
	local result = 0
	
	for i = mw.ustring.len(roman), 1, -1 do
		local c = mw.ustring.sub(roman, i, i)
		
		local currentRomanDecimal = romanDecimals[c]
		if currentRomanDecimal == nil then
			return 0
		end
		
		if prevRomanDecimal > currentRomanDecimal then
			result = result - currentRomanDecimal
		else
			result = result + currentRomanDecimal
		end
		prevRomanDecimal = currentRomanDecimal
	end
	
	return result
end


--[[
Helper function to handle error messages.
]]
function outputError(error_str)
    local error_str = '<strong class="error">Roman Module Error: ' .. error_str .. '</strong>';
    error_str = '[[Category:Errors reported by Module Roman]]' .. error_str;
 
    return error_str;
end

return p
Cookies help us deliver our services. By using our services, you agree to our use of cookies.