Module:MathRoman
Appearance
Documentation for this module may be created at Module:MathRoman/doc
--[[
Ce Module:MathRoman :
convertit des nombres entiers en nombres romains et vice-versa,
génère des erreurs précises sur le nombre entré,
génère des erreurs sur les limites de conversion,
permet d'afficher des tests de ces fonctions.
]]--
local p = {}
function p.erreur_color(t)
return '<span style="color:red;" >' .. tostring(t) .. '</span>'
end
function p.roman2int(rm, err)
if ( rm == nil ) then rm = '' end
if ( err == nil ) then err = '' end
if ( rm == '' ) then return '' end
local v = 0 -- valeur totale
local v1 = 0 -- valeur de derniere lettre
local v2 = 0 -- valeur de lettre precedente
local v3 = 0 -- valeur de lettre precedente
local x = '-' -- caractere en cours d'evaluation
local i = 0 -- numéro du caractere en cours d'evaluation
local j = 0 -- numéro du caractere de reference courant (debut en Lua)
local k = 0 -- numéro du caractere de reference courant (fin en Lua)
local e0 = '' -- texte d'erreur
local e1 = '' -- texte d'erreur
local e2 = '' -- texte d'erreur
local e3 = '' -- texte d'erreur
local e4 = '' -- texte d'erreur
local lst = '-MDCLXVIJ' -- caracteres autorises
while (x ~= '') do
v3 = v2
v2 = v1
v1 = 0
x = string.sub(rm, i, i)
if ( x == 'M' ) then v1 = 1000 end
if ( x == 'D' ) then v1 = 500 end
if ( x == 'C' ) then v1 = 100 end
if ( x == 'L' ) then v1 = 50 end
if ( x == 'X' ) then v1 = 10 end
if ( x == 'V' ) then v1 = 5 end
if ( x == 'I' ) then v1 = 1 end
if ( x == 'J' ) then
v1 = 1
if ( i < ( string.len(rm) - 0 ) )
then e4 = ' erreur caractere J avant la fin.' end
end
v = v + v1
if ( (v1 == 5*v2) or (v1 == 10*v2) ) then v = v - (2*v2) end -- ajuster 4, 9, 40, 90 ...
j, k = string.find(lst, x)
if ( j == nil ) then j = -1 end
if ( k == nil ) then k = -1 end
if ( j < 1 ) then e3 = ' erreur caractere '..x..' en '..i..'.' end
if ( (v1 > v2) and (v2 > v3) ) then e2 = ' caracteres croissants.' end
i = i + 1
x = string.sub(rm, i, i)
end
if ( v == 0 ) then e0 = ' valeur nulle.' end
if ( v > 4999 ) then e1 = ' valeur > 4999.' end
if ( ( e0..e1..e2..e3..e4 > '' ) and ( err > '' ) ) then
err = ''..err..e0..e1..e2..e3..e4 -- sortie avec les erreurs
else
err = '' -- sortie sans les erreurs
end
return v, err -- avec ou sans erreurs
end -- function p.roman2int(rm, err)
function p.romani2r(i, j)
if ( j == nil ) then j = '' end
local rm=''
if ( i == 1000 ) then rm = 'M' end
if ( i == 500 ) then rm = 'D' end
if ( i == 100 ) then rm = 'C' end
if ( i == 50 ) then rm = 'L' end
if ( i == 10 ) then rm = 'X' end
if ( i == 5 ) then rm = 'V' end
if ( i == 1 ) then
rm = 'I'
if ( j == 'J' ) then rm = 'J' end
end
return rm
end -- function p.romani2r(i, j)
function p.int2roman(i, err)
local n = 0
if ( i == nil ) then n = 0 else n = i end -- anti null
if ( type(n) ~= 'number' ) then n = tonumber(n) end
if ( type(n) ~= 'number' ) then n = 0 end
n = math.floor(n) -- input:89: bad argument #1 to 'floor' (number expected, got nil)
-- if ( type (v) ~= 'number' ) then i = 0 end -- anti nil
-- i = i.valueOf()
if ( err == nil ) then err = ' ' end -- anti null, to text
local v100 = 100
local v500 = v100*5
local v1000 = v100*10 -- cycle romain 1000, 100, 10, 1
local v=0
local v1=0
local v2=0
local v3=0 -- valeurs totale, derniere, et precedentes
local reste=0
local reduction=0 -- reste a convertir, derniere reduction
--local x='-' local i=0 -- caractere courant et son numéro
--local lst='-MDCLXVIJ' -- liste des chiffres romains
local rm=''
local roman='' -- chiffre et nombre romain resultant
local e0=''
local e1=''
local e2=''
local e3=''
local e4='' -- erreurs detectables
if ( n > 4999 ) then
e1 = ' valeur > 4999.'
roman = 'ERREUR'
n = 0
end
if ( n < 1 ) then
e2 = ' valeur < 1.'
roman = 'ERREUR'
n = 0
end
reste = n
-- return ' test ' -- temporaire
while (reste > 0) do
v3 = v2
v2 = v1
v1 = reste
reduction = 0
if ( reste >= v1000 ) then
reduction = v1000
elseif ( reste >= v100*9 ) then
reduction = v100
reste = reste + v100*2
elseif ( reste >= v500 ) then
reduction = v500
elseif ( reste >= v100*4 ) then
reduction = v100
reste = reste + v100*2
elseif ( reste >= v100 ) then
reduction = v100
elseif ( reste >= 1000 ) then
v100 = 100
v1000 = 1000
reduction = v1000
end
rm = p.romani2r(reduction)
roman = roman..rm
reste = reste - reduction
if ( reste < v100 ) then
if ( v100 >= 10 ) then
v100 = v100/10
v500 = v100*5
v1000 = v100*10
end
end
end
-- if ( v == 0 ) then e0 = ' valeur nulle.' end
-- if ( v > 4999 ) then e1 = ' valeur > 4999.' end
if ( ( e0..e1..e2..e3..e4 > '' ) and ( err > '' ) ) then
err = ''..err..e0..e1..e2..e3..e4 -- sortie avec les erreurs
else
err = '' -- sortie sans les erreurs
end
return roman, err -- avec ou sans erreurs
end -- function p.int2roman(in, err)
function p.testerUnRomain(r1, view)
if ( r1 == nil ) then r1 = '' end
if ( view == nil ) then view = '' end
if ( view == '' ) then view = '%s' end
local i, erri = p.roman2int(r1, ' Erreur r2i : ')
local rm, errm = p.int2roman(i, ' Erreur i2r : ')
local s = r1 .. " = '''" .. i .. "''' = " .. rm .. " "
if ( erri == nil ) then erri = '' end
if ( errm == nil ) then errm = '' end
if ( ( erri ~= '' ) or ( errm ~= '' ) ) then
s = s .. " -> " .. p.erreur_color( erri ) .. " '''-''' " .. p.erreur_color( errm )
end
return string.format(view, s)
-- return string.format("Hello, %s!", s)
end -- function p.testerUnRomain(r1, view)
function p.erreurUnRomain(r1, view)
if ( r1 == nil ) then r1 = '' end
if ( view == nil ) then view = '' end
if ( view == '' ) then view = '%s' end
local i, erri = p.roman2int(r1, ' Erreur r2i : ')
local s = " - " .. r1 .. " -> '''" .. i .. "''' "
if ( erri == nil ) then erri = '' end
if ( erri ~= '' ) then
s = s .. ' -> ' .. p.erreur_color( erri )
end
return string.format(view, s)
-- return string.format("Hello, %s!", s)
end -- function p.erreurUnRomain(r1, view)
function p.testerDesRomains(view)
if ( view == nil ) then view = '' end
if ( view == '' ) then view = '%s' end
view = '\n* %s'
local s = ''
s = s .. "\n;Tests sans erreurs :"
s = s .. p.testerUnRomain('XIJ', view)
s = s .. p.testerUnRomain('XIJ', view)
s = s .. p.testerUnRomain('MCXI', view)
s = s .. p.testerUnRomain('MCDXLIV', view)
s = s .. p.testerUnRomain('MDCLXVI', view)
s = s .. p.testerUnRomain('MCMXCIX', view)
s = s .. p.testerUnRomain('MMCCXXII', view)
s = s .. p.testerUnRomain('MMMMCMXCIX', view)
s = s .. "\n;Tests avec erreurs :"
s = s .. p.testerUnRomain('i', view)
s = s .. p.testerUnRomain('XIA', view)
s = s .. p.testerUnRomain('XJI', view)
s = s .. p.testerUnRomain('IXC', view)
s = s .. p.testerUnRomain('VLD', view)
s = s .. p.testerUnRomain('', view)
s = s .. p.testerUnRomain(nil)
s = s .. p.erreurUnRomain('XIA', view)
s = s .. p.erreurUnRomain('XJI', view)
s = s .. p.erreurUnRomain('IXC', view)
s = s .. p.erreurUnRomain('VLD', view)
s = s .. "\n;Nombres hors limites :"
s = s .. p.testerUnRomain('MMMMM', view)
s = s .. p.testerUnRomain('MMMMMYJXC', view)
s = s .. p.erreurUnRomain('MMMMM', view)
s = s .. p.erreurUnRomain('MMMMMYJXC', view)
s = s .. p.testerUnRomain('ERREURS', view)
s = s .. p.erreurUnRomain('ERREURS', view)
return s
end -- function p.testerDesRomains(view)
-- p.testerDesRomains('x') -- lance le test
-- Interface http://scribunto.wmflabs.org/
------------------------------------------------------------
-- Tests internes. Internal tests.
------------------------------------------------------------
function p.roman2integer(frame)
-- { {#invoke:MathRoman.lua|p.roman2integer| MMXIJ } }
local r = frame.args[1]
local i, erri = p.roman2int(r, ' Error r2i : ')
return i
end
function p.r2i(frame) -- shortcut of p.roman2integer
-- { {#invoke:MathRoman.lua|r2i| MMXIJ } }
return p.roman2integer(frame)
end
function p.integer2roman(frame)
-- { {#invoke:MathRoman.lua|integer2roman| 2012 } }
local i = frame.args[1]
local r, errr = p.int2roman(i, ' Error i2r : ')
return r
end
function p.i2r(frame) -- shortcut of integer2roman
-- { {#invoke:MathRoman.lua|i2r| MMXIJ } }
return p.integer2roman(frame)
end
function p.testRomans(frame)
-- { {#invoke:MathRoman.lua|testRomans|': %s<br/>'} }
local view = frame.args[1]
if ( view == nil ) then view = '' end
if ( view == '' ) then view = '%s' end
local s = p.testerDesRomains(view)
return s
end
function p.autotests(frame)
-- { {#invoke:MathRoman.lua|testRomans|': %s<br/>'} }
local view = frame.args[1]
if ( view == nil ) then view = '' end
if ( view == '' ) then view = '%s' end
local s = p.testerDesRomains(view)
return s
end
function p.testText(formater, text, n)
-- { {#invoke:MathRoman.lua|testText|': %s<br/>'|Text under test. |3} }
local s = ''
local N = tonumber(n)
while ( N > 0 ) do
s = s .. string.format(formater, text)
N = N - 1
end
return s
end
return p