Module:Roman: Διαφορά μεταξύ των αναθεωρήσεων

Περιεχόμενο που διαγράφηκε Περιεχόμενο που προστέθηκε
Gts-tg (συζήτηση | συνεισφορές)
επικαιροποίηση βάση τελευταίας έκδοση από en
RexxS (συζήτηση | συνεισφορές)
updated from https://commons.wikimedia.org/w/index.php?title=Module:Roman&oldid=411628424
Γραμμή 1:
--[[
-- This module implements {{Roman}}.
This module converts Arabic numerals into Roman numerals.
It currently works for any non-negative integer below 5 billions (up to 4 999 999 999).
 
Zero is represented as "N" (from Classical Latin adverbs "nec" or "non"), like in standard CLDR data.
 
For numbers starting at 4 thousands, this version no longer generates any HTML+CSS, but only plain-text:
standard Unicode combining diacritics are used for overlines (U+0305 for the first level,
then U+0304 for the second level, but both are treated equivalently when parsing Roman numbers).
 
For numbers starting at 4 billions, it still uses 4 letters M with double overlines because
triple overlines are not supported in plain-text (this is acceptable, just like "MMMM" is also
acceptable for representing 4000 but this version chooses the shorter "IV" with a single overline).
 
The Roman number parser will accept all valid notations (except apostrophic/Claudian/lunate notations
using reversed C), more than what it generates, and will correctly convert them to Arabic numbers.
 
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, User:Verdy_p
]]
local p = {}
 
--[============[
-- This function implements the {{overline}} template.
Private data
local function overline(s)
--]============]
return mw.ustring.format( '<span style="text-decoration:overline;">%s</span>', s )
-- See CLDR data /common/rbnf/root.xml for "roman-upper" rules. However we still don't
-- use the rarely supported Roman extension digits after 'M' (in U+2160..2188), but use
-- the more common notation with diacritical overlines ('ↁ'='V̅', 'ↂ'='X̅', etc.).
-- Please avoid using HTML with "text-decoration:overline" style, but use plain-text
-- combining characters (U+0304 and/or U+0305).
local decimalRomans = {
d0 = { [0] = '', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX' },
d1 = { [0] = '', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC' },
d2 = { [0] = '', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM' },
d3 = { [0] = '', 'M', 'MM', 'MMM', 'I̅V̅', 'V̅', 'V̅I̅', 'V̅I̅I̅', 'V̅I̅I̅I̅', 'I̅X̅' },
d4 = { [0] = '', 'X̅', 'X̅X̅', 'X̅X̅X̅', 'X̅L̅', 'L̅', 'L̅X̅', 'L̅X̅X̅', 'L̅X̅X̅X̅', 'X̅C̅' },
d5 = { [0] = '', 'C̅', 'C̅C̅', 'C̅C̅C̅', 'C̅D̅', 'D̅', 'D̅C̅', 'D̅C̅C̅', 'D̅C̅C̅C̅', 'C̅M̅' },
d6 = { [0] = '', 'M̅', 'M̅M̅', 'M̅M̅M̅', 'I̿V̿', 'V̿', 'V̿I̿', 'V̿I̿I̿', 'V̿I̿I̿I̿', 'I̿X̿' },
d7 = { [0] = '', 'X̿', 'X̿X̿', 'X̿X̿X̿', 'X̿L̿', 'L̿', 'L̿X̿', 'L̿X̿X̿', 'L̿X̿X̿X̿', 'X̿C̿' },
d8 = { [0] = '', 'C̿', 'C̿C̿', 'C̿C̿C̿', 'C̿D̿', 'D̿', 'D̿C̿', 'D̿C̿C̿', 'D̿C̿C̿C̿', 'C̿M̿' },
d9 = { [0] = '', 'M̿', 'M̿M̿', 'M̿M̿M̿', 'M̿M̿M̿M̿' },
}
local romanDecimals = {
-- Basic Latin capital letters
N = 0, -- abbreviated "nec" or "non" adverb in Classical Latin
I = 1, V = 5, X = 10, L = 50, C = 100,
D = 500,-- TODO: add Medieval "apostrophic/Claudian/lunate" notations like "IƆ"
M = 1000,
-- Basic Latin small letters (not used in Classical Latin, but added in Medieval Latin)
n = 0, -- abbreviated "nec" or "non" adverb in Classical Latin
i = 1, v = 5, x = 10, l = 50, c = 100,
d = 500,-- TODO: add Medieval "apostrophic/Claudian/lunate" notations like "IƆ"
m = 1000,
-- U+0304 .. U+0305 : COMBINING (MACRON|OVERLINE)
['\204\132'] = -1000, -- (0xCC,0x84 in UTF-8) multiplier (thousand)
['\204\133'] = -1000, -- (0xCC,0x85 in UTF-8) multiplier (thousand), considered equivalent here
-- U+033F : COMBINING DOUBLE OVERLINE
['\204\191'] = -1000000, -- (0xCC,0xBF in UTF-8) multiplier (million)
-- U+012A
['Ī'] = 1000, ['ī'] = 1000, -- LATIN LETTER WITH COMBINING MACRON, canonically equivalent to 'I' and U+0304
-- U+2160 .. U+216F : Roman capital digit symbols (compatibility, monospaced in CJK fonts)
['Ⅰ'] = 1, ['Ⅱ'] = 2, ['Ⅲ'] = 3, ['Ⅳ'] = 4, ['Ⅴ'] = 5, ['Ⅵ'] = 6,
['Ⅶ'] = 7, ['Ⅷ'] = 8, ['Ⅸ'] = 9, ['Ⅹ'] = 10, ['Ⅺ'] = 11, ['Ⅻ'] = 12,
['Ⅼ'] = 50, ['Ⅽ'] = 100, ['Ⅾ'] = 500, ['Ⅿ'] = 1000,
-- U+2170 .. U+217F : Roman lowercase digit symbols (compatibility, monospaced in CJK fonts)
['ⅰ'] = 1, ['ⅱ'] = 2, ['ⅲ'] = 3, ['ⅳ'] = 4, ['ⅴ'] = 5, ['ⅵ'] = 6,
['ⅶ'] = 7, ['ⅷ'] = 8, ['ⅸ'] = 9, ['ⅹ'] = 10, ['ⅺ'] = 11, ['ⅻ'] = 12,
['ⅼ'] = 50, ['ⅽ'] = 100, ['ⅾ'] = 500, ['ⅿ'] = 1000,
-- U+2180 .. U+2182 : Old Roman symbols (these have no case pairs)
['ↀ'] = 1000, -- = 'I̅' = 'M'. TODO: add Medieval "apostrophic/Claudian/lunate" notations like "CIƆ"; do not confuse it with "CD" (400)
['ↁ'] = 5000, -- = 'V̅'. TODO: add Medieval "apostrophic/Claudian/lunate" notations like "DƆ" and "IƆƆ"
['ↂ'] = 10000, -- = 'X̅'. TODO: add Medieval "apostrophic/Claudian/lunate" notations like "CCIƆƆ"
-- U+2183..U+2184 : ROMAN DIGIT (CAPITAL|LOWER) REVERSED C. TODO: add for "apostrophic/Claudian/lunate" notations (and support "Ɔ" OPEN O as aliases)
-- The reversed "C" is a trailing multiplier by 10 but if it is not paired by a leading "C", the surrounded value will be divided by 2:
-- * "I" = 1, but if followed by followed by "Ɔ", it takes the value 100:
-- * when followed by a first "Ɔ" it multiplies it by 10 giving 1000 (assuming "CIƆ"), but if not prefixed by a pairing "C", gives 500 for "IƆ" = "D".
-- * when followed by a second "Ɔ" it multiplies it by 10 giving 1000 (assuming "CCIƆƆ"), but if not prefixed by a pairing "C", gives 5000 for "IƆƆ" = "DƆ".
-- * for higher multiples, using overlines is highly preferred for noting multipliers by 1000.
-- U+2185: ROMAN NUMERAL SIX LATE FORM
['ↅ'] = 6, -- = 'VI' (overstriked letters)
-- U+2186: ROMAN NUMERAL FIFTY EARLY FORM (Borrowed in Latin in capital form, from Greek Final sigma, similar to "C" with a leg meaning "half")
['ↆ'] = 50, -- = 'L'
-- U+2187 .. U+2188: ROMAN NUMERAL (ONE HUNDRED|FIFTY) THOUSAND (Archaic, rarely supported in fonts)
['ↇ'] = 50000, -- = 'L̅'. TODO: add Medieval "apostrophic/Claudian/lunate" notations like "DƆƆ" and "IƆƆƆ"
['ↈ'] = 100000, -- = 'C̅'. TODO: add Medieval "apostrophic/Claudian/lunate" notations like "CCCDƆƆ" and "CCCIƆƆƆ"
}
 
--[=================[
Private functions
--]=================]
 
--[==[
This function returns a string containing the input value formatted as a Roman numeral.
It works for non-negative integers lower than 5 billions (up to 4 999 999 999: this covers
all unsigned 32-bit integers), otherwise it returns the number formatted using Latin
digits. The result string will be an UTF-8-encoded plain-text alphabetic string.
]==]--
local function convertArabicToRoman(value)
if value and value >= 1 and value <= 4999999999 and value == math.floor(value) then
local d0, d1, d2, d3, d4, d5, d6, d7, d8
d0, value = value % 10, math.floor(value / 10)
d1, value = value % 10, math.floor(value / 10)
d2, value = value % 10, math.floor(value / 10)
d3, value = value % 10, math.floor(value / 10)
d4, value = value % 10, math.floor(value / 10)
d5, value = value % 10, math.floor(value / 10)
d6, value = value % 10, math.floor(value / 10)
d7, value = value % 10, math.floor(value / 10)
d8, value = value % 10, math.floor(value / 10)
return table.concat({
decimalRomans.d9[value],
decimalRomans.d8[d8],
decimalRomans.d7[d7],
decimalRomans.d6[d6],
decimalRomans.d5[d5],
decimalRomans.d4[d4],
decimalRomans.d3[d3],
decimalRomans.d2[d2],
decimalRomans.d1[d1],
decimalRomans.d0[d0],
})
elseif value == 0 then
return 'N' -- for adverbs "nec" or "non" in Classical Latin (which had no zero)
end
return tostring(value)
end
 
--[==[
-- Gets the Roman numerals for a given numeral table. Returns both the string of
This function converts a plain-text string containing a Roman numeral to an integer.
-- numerals and the value of the number after it is finished being processed.
It works for values between 0 (N) and 4 999 999 999 (M̿M̿M̿M̿C̿M̿X̿C̿I̿X̿C̅M̅X̅C̅I̅X̅CMXCIX).
local function getLetters(num, t)
]==]--
local ret = {}
local function convertRomanToArabic(roman)
for _, v in ipairs(t) do
if roman == '' localthen val,return letter =nil unpack(v)end
local result, prevRomanDecimal, multiplier = 0, 0, 1
while num >= val do
for i = mw.ustring.len(roman), 1, -1 do
num = num - val
local currentRomanDecimal = romanDecimals[mw.ustring.sub(roman, i, i)]
table.insert(ret, letter)
if currentRomanDecimal == nil then
return nil
elseif currentRomanDecimal < 0 then
multiplier = multiplier * -currentRomanDecimal
else
currentRomanDecimal, multiplier = currentRomanDecimal * multiplier, 1
if currentRomanDecimal < prevRomanDecimal then
result = result - currentRomanDecimal
else
result = result + currentRomanDecimal
prevRomanDecimal = currentRomanDecimal
end
end
end
return result
 
return table.concat(ret), num
end
 
--[==[
-- The main control flow of the module.
This function converts a string containing a Roman numeral to an integer.
local function _main(args)
It works for values between 0 and 4999999999.
-- Get input and exit displaying nothing if the input is empty.
The input string may contain HTML tags using style="text-decoration:overline" (not recommended).
if args[1] == nil then return end
]==]--
local num = tonumber(args[1])
local function convertRomanHTMLToArabic(roman)
if not num or num < 0 or num == math.huge then
local result = convertRomanToArabic(roman)
error('Invalid number ' .. args[1], 2)
elseifif numresult == 0nil then
returnresult 'N'= tonumber(roman)
end
return result
 
[==[ DISABLED FOR NOW, NOT REALLY NEEDED AND NOT CORRECTLY TESTED
-- Return a message for numbers too big to be expressed in Roman numerals.
iflocal numresult >= 5000000 then0
local overline_start_len = mw.ustring.len(overline_start)
return args[2] or 'N/A'
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
return result
]==]
end
 
--[==[
local ret = ''
Helper function to handle error messages.
-- Find the Roman numerals for the large part of numbers.
]==]--
-- 23 April 2016 - tweaked to >= 4000 to accept big Roman 'IV'
local function outputError(message)
-- The if statement is not strictly necessary, but makes the algorithm
return table.concat({
-- more efficient for smaller numbers.
'<strong class="error">Roman Module Error: ', message,
if num >= 4000 then
'</strong>[[Category:Errors reported by Module Roman]]'
local bigRomans = {
})
{ 1000000, 'M' },
end
{ 900000, 'CM' }, { 500000, 'D' }, { 400000, 'CD' }, { 100000, 'C' },
{ 90000, 'XC' }, { 50000, 'L' }, { 40000, 'XL' }, { 10000, 'X' },
{ 9000, 'IX' }, { 5000, 'V' }, { 4000, 'IV' },
}
local bigLetters
bigLetters, num = getLetters(num, bigRomans)
ret = overline(bigLetters)
end
 
--[================[
-- Find the Roman numerals for numbers less than the big Roman threshold.
Public functions
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
 
--[==[
if args.fraction == 'yes' then
isRoman
-- Find the Roman numerals for the fractional parts of numbers.
 
-- If num is not a whole number, add half of 1/1728 (the smallest unit) to equate to rounding.
Tests if the trimmed input is a valid Roman numeral. Returns true if so, false if not.
-- Ensure we're not less than the smallest unit or larger than 1 - smallest unit
For the purposes of this function, the empty string (after trimming whitespaces) is not a Roman numeral.
-- to avoid getting two "half" symbols or no symbols at all
 
num = num - math.floor(num)
Parameters
if num ~= 0 then
s: string to test if it is a valid Roman numeral
num = math.max(1.1/1728, math.min(1727.1/1728, num + 1/3456))
end
local fractionalRomans = {
{ 1/2, 'S' }, { 5/12, "''':'''•''':'''" }, { 1/3, "'''::'''" },
{ 1/4, "''':'''•" }, { 1/6, "''':'''" }, { 1/12, '•' },
{ 1/24, 'Є' }, { 1/36, 'ƧƧ' }, { 1/48, 'Ɔ' }, { 1/72, 'Ƨ' }, { 1/144, 'ƻ' },
{ 1/288, '℈' }, { 1/1728, '»' },
}
local fractionalLetters = getLetters(num, fractionalRomans)
ret = ret .. fractionalLetters
end
 
Error Handling:
return ret
If the input is not a valid Roman numeral this function returns false.
]==]--
function p.isRoman(s)
return type(s) == 'string' and convertRomanToArabic(mw.text.trim(s)) ~= nil
end
 
--[==[
function p.main(frame)
toArabic
-- If called via #invoke, use the args passed into the invoking
 
-- template, or the args passed to #invoke if any exist. Otherwise
This function converts a Roman numeral into an Arabic numeral.
-- assume args are being passed directly in from the debug console
It works for values between 0 and 4999999999.
-- or from another Lua module.
'N' is converted to 0 and the empty string is converted to nil.
local origArgs
 
if frame == mw.getCurrentFrame() then
Parameters
origArgs = frame:getParent().args
roman: string containing value to convert into an Arabic numeral
for k, v in pairs(frame.args) do
 
origArgs = frame.args
Error Handling:
break
If the input is not a valid Roman numeral this function returns nil.
]==]--
function p.toArabic(roman)
if type(roman) == 'string' then
roman = mw.text.trim(roman)
local result = convertRomanToArabic(roman)
if result == nil then
result = tonumber(roman)
end
return result
elseif type(roman) == 'number' then
return roman
else
origArgsreturn = framenil
end
end
-- Trim whitespace and remove blank arguments.
 
local args = {}
--[==[
for k, v in pairs(origArgs) do
_Numeral
if type( v ) == 'string' then
 
v = mw.text.trim(v)
This function returns a string containing the input value formatted as a Roman numeral.
end
It works for values between 0 and 4999999999.
if v ~= '' then
 
args[k] = v
Parameters
end
value: 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(value)
if value == nil then
return outputError('missing value')
end
if type(value) == 'string' then
-- exit if not givenvalue anything= tonumber(value)
ifelseif argstype(value) =~= nil or args == {}'number' then return end
return outputError('unsupported value')
-- Given mathematical expression, simplify to a number
end
if type(args[1]) == 'string' then
return convertArabicToRoman(value)
args[1] = mw.ext.ParserFunctions.expr(args[1])
end
 
--[==[
Numeral
 
This function for MediaWiki converts an Arabic numeral into a Roman numeral.
It works for values between 0 and 4999999999 (includes the whole range of unsigned 32-bit integers).
Arabic numeral zero is output as 'N' (for Latin negation adverbs "nec" or "non").
 
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 _mainp._Numeral(args[1])
end
 
Ανακτήθηκε από "https://el.wikipedia.org/wiki/Module:Roman"