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.
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:
Schrijf een functie romeins2arabisch die een gegeven string die enkel bestaat uit Romeinse cijfers (hoofdletters of kleine letters) omzet naar een integervoorstelling van hetzelfde getal.
Schrijf een functie arabisch2romeins die een gegeven
integer omzet naar de stringvoorstelling van dezelfde waarde in
Romeinse cijfers (enkel hoofdletters). Deze omzetting kan gebeuren
door onderstaande tabel van links naar rechts te doorlopen. Zolang de
resterende integerwaarde groter of gelijk is aan de getalwaarde uit de
tabel, voeg je de combinatie van Romeinse cijfers op de
corresponderende positie achteraan toe aan het Romeins getal. De
integerwaarde wordt daarna verlaagd met de getalwaarde. Van zodra de
resterende integerwaarde kleiner is dan de getalwaarde uit de tabel,
spring je één positie naar rechts in de tabel.
M | CM | D | CD | C | XC | L | XL | X | IX | V | IV | I |
1000 | 900 | 500 | 400 | 100 | 90 | 50 | 40 | 10 | 9 | 5 | 4 | 1 |
Definieer een klasse Romeins waarmee Romeinse getallen kunnen voorgesteld worden in Python. Nieuwe objecten van deze klasse kunnen zowel geïnitialiseerd worden met een integerwaarde $$i$$ (waarvoor $$1 \leq i < 4000$$) of met een string $$s$$ die enkel bestaat uit Romeinse cijfers (hoofdletters of kleine letters). Voor andere initialisatiewaarden moet de klasse een AssertionError opwerpen met de string ongeldig romeins cijfer. De conversie van een Romeins getal naar een string — bekomen met de ingebouwde functies str() en repr() — geeft de getalwaarde in Romeinse cijfers (hoofdletters, zoals gegenereerd door de functie arabisch2romeins) en de conversie naar een integer — bekomen met de ingebouwde functie int() — geeft de getalwaarde in Arabische cijfers. Zorg ervoor dat de som, het verschil en het product van twee Romeinse getallen kan berekend worden aan de hand van de operatoren +, - en *. De evaluatie van deze bewerkingen moet resulteren in een nieuw Romeins getal.
>>> 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