Aller au contenu

Module:Romain

Cette page fait l’objet d’une mesure de semi-protection étendue.
Une page de Wikipédia, l'encyclopédie libre.
Ceci est une version archivée de cette page, en date du 8 août 2016 à 19:46 et modifiée en dernier par Zebulon84 (discuter | contributions) (Ajout fonction fromRoman, et les fonctions permettant d'utiliser le module depuis un modèle). Elle peut contenir des erreurs, des inexactitudes ou des contenus vandalisés non présents dans la version actuelle.

 Documentation[créer] [purger]
local p = {}

-- barre horizontale au-dessus des nombres élevés
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


function p.toRoman(num, default)
    num = tonumber(num)
    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 default 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.fromRoman( str, default )
	str = str:upper()
	if not str:find( '^[MDCLXVI]+$' ) then
		if default then
			return default
		else
			error( 'fromRoman expect a string containing only M, D, C, L, X, V or I letters' )
		end
	end
	local smallRomans = { I = 1, V = 5, X = 10, L = 50, C = 100, D = 500, M = 1000 }
	local result = 0
	local old, n = 0
	for i = str:len(), 1, -1  do
		n = smallRomans[ str:sub( i, i ) ]
		if n < old then
			result = result - n
		else
			result = result + n
			old = n
		end
	end
	return result
end

-- compatibilité avec [[en:Module:Roman]]
function p._main(args)
	return p.toRoman( args[1] )
end

function p.main( frame )
	return p.nombreEnRomain( frame )
end

function p.nombreEnRomain( frame )
	local num
	if frame == mw.getCurrentFrame() then
		num = frame.args[1] or frame:getParent().args[1]
	else
		num = frame
	end
	return p.toRoman( mw.text.trim( num ) )
end

function p.nombreDepuisRomain( frame )
	local num
	if frame == mw.getCurrentFrame() then
		num = frame.args[1] or frame:getParent().args[1]
	else
		num = frame
	end
	return p.fromRoman( mw.text.trim( num ) )
end
	
return p