In het oude Rome gebruikte men een talstelsel gebaseerd op Romeinse cijfers voor het weergeven van natuurlijke getallen. Dit talstelsel is geen positiestelsel, maar een additief stelsel waarin de waarde van het voorgestelde getal bepaald wordt door het totaal van de samenstellende symbolen. De getallen één tot en met tien worden met Romeinse cijfers geschreven als: I, II, III, IV, V, VI, VII, VIII, IX en X. Negatieve getallen en het getal nul kunnen niet voorgesteld worden in Romeinse cijfers. Het talstelsel is sinds de veertiende eeuw grotendeels verlaten ten voordele van het decimaal talstelsel gebaseerd op Arabische cijfers. In sommige toepassingen zijn Romeinse cijfers echter nog steeds in gebruik, bijvoorbeeld bij de nummering van vorsten met dezelfde naam (bijv. Lodewijk XIV), bij de nummering van jaarlijkse events en bij de nummering van eeuwen in sommige landen (bijv. XIXe siècle).

In het talstelsel met Romeinse cijfers worden getallen genoteerd met symbolen, de eigenlijke cijfers, waarvan elk een bepaalde waarde heeft die onafhankelijk is van de positie die het cijfer in het getal inneemt. De Romeinse cijfers zijn:

symbool waarde
I 1
V 5
X 10
L 50
C 100
D 500
M 1000

De volgorde van de Romeinse cijfers in een getal is niet willekeurig. De waarden van de losse cijfers worden bij elkaar opgeteld, behalve als een lager cijfer vóór een hoger cijfer staat: in dat geval wordt het lagere cijfer er van afgetrokken. De regels voor het schrijven van getallen met Romeinse cijfers lijken in de Oudheid zeer los te zijn geweest. Zo gebruikte de BBC voor de aftiteling in het jaar 1999 het typografisch elegante jaartal MIM in plaats van MCMXCIX.

Opgave

PEP 3131 was een voorstel om de Python programmeertaal uit te breiden met ondersteuning voor Romeinse getallen. Dit voorstel werd echter niet goedgekeurd. Omdat Python toelaat om nieuwe gegevenstypes te definiëren, is het echter mogelijk om zelf een gegevenstype voor Romeinse getallen toe te voegen aan Python. Hiervoor ga je als volgt te werk:

Voorbeeld

>>> romeins2arabisch('MDCCCCX')
1910

>>> arabisch2romeins(1910)
'MCMX'

>>> int(Romeins('MDCCCCX'))
1910
>>> int(Romeins('MCMLIV'))
1954
>>> int(Romeins('MCMXC'))
1990
>>> som = Romeins('MDCCCCX') + Romeins('MCMXC')
>>> isinstance(som, Romeins)
True
>>> print(som)
MMMCM
>>> verschil = Romeins('MCMXC') - Romeins('MDCCCCX')
>>> isinstance(verschil, Romeins)
True
>>> str(verschil)
'LXXX'
>>> product = Romeins('CMX') * Romeins('III')
>>> isinstance(product, Romeins)
True
>>> product
MMDCCXXX

>>> print(Romeins('mdccccx'))
MCMX
>>> Romeins(1234)
MCCXXXIV
>>> Romeins(4321)
Traceback (most recent call last):
AssertionError: ongeldig romeins cijfer
>>> Romeins('ABCDEF')
Traceback (most recent call last):
AssertionError: ongeldig romeins cijfer
>>> Romeins(3.14)
Traceback (most recent call last):
AssertionError: ongeldig romeins cijfer