Nei capitoli precedenti, ci si è “tuffati”
immediatamente nell'analisi del codice, cercando poi di
capirlo il più velocemente possibile. Ora che avete
immagazzinato un po' di Python, faremo un passo
indietro e analizzeremo ciò che si fa
prima di scrivere il codice.
In questo capitolo scriveremo una serie di funzioni utili per
convertire da numeri arabi a numeri romani e viceversa. Molto
probabilmente avete già visto dei numeri romani, anche se
spesso non li avete riconosciuti. Potete averli visti nella
nota di copyright di vecchi film e spettacoli televisivi
(“Copyright MCMXLVI” invece
di “Copyright 1946”), oppure
nelle targhe di dedica di biblioteche e università
(“fondata MDCCCLXXXVIII” invece
di “fondata 1888”). Potete
averli visti in sommari e riferimenti bibliografici. È un
sistema di rappresentare numeri che effettivamente risale
all'antico Impero Romano (da cui il nome).
Nei numeri romani, ci sono sette caratteri che sono ripetuti
e combinati in vari modi per rappresentare i numeri:
- I = 1
- V = 5
- X = 10
- L = 50
- C = 100
- D = 500
- M = 1000
Ecco alcune regole generali per costruire numeri romani:
-
Il valore del numero è la somma dei valori dei caratteri.
I è 1, II
è 2, e III
è 3. VI
è 6 (letteralmente, “5
e 1”), VII
è 7 e VIII
è 8.
-
I “caratteri di decina”
(I, X,
C, e M)
possono esere ripetuti fino a tre volte.
Alla quarta, si deve sottrarre uno dal piu vicino
“carattere di quintina”
(V, L,
D). Non si può rappresentare
4 come IIII;,
lo si deve rappresentare con IV
(“1 in meno di
5”). 40 è
scritto come XL, 41
come XLI, 42 come
XLII, 43 come
XLIII ed infine 44
come XLIV (“10
in meno di 50, più uno in meno di
5”).
-
Similmente, arrivati al 9, si deve
sottrarre dal carattere di decina immediatamente
superiore: 8 è VIII,
ma 9 è IX
(“uno in meno di dieci”), non
VIIII (giacché il carattere
I non può essere ripetuto quattro volte).
90 è XC,
900 è CM.
-
I caratteri di quintina non possono essere ripetuti.
10 è sempre rappresentato come
X, mai come VV.
100 è sempre C,
mai LL.
-
I numeri romani sono sempre scritti dal più grande al più
piccolo e letti da sinistra a destra. per cui l'ordine dei
caratteri è molto importante. DC è
600; CD è un numero
completamente diverso (400,
“100 meno di
500”).
CI è 101;
IC non è neppure un numero romano valido
(perché non si può sottrarre 1 direttamente
da 100; 99 si deve
scrivere XCIX, “10
in meno di 100 e poi 1
in meno di 10”).
Queste regole conducono ad alcune interessanti osservazioni:
-
C'è solo un modo corretto di rappresentare
una quantità come numero romano.
-
Il viceversa è anche vero: se una sequenza di caratteri è
un valido numero romano, essa rappresenta una quantità univoca
(i.e. può essere letto in una sola maniera)
-
C'è un numero finito di numeri arabi che possono essere
espressi come numeri romani, specificatamente da
1 a 3999.
I romani avevano diversi modi di esprimere quantità
più grandi, per esempio mettendo una barra su un numero
per indicare che la sua quantità doveva essere moltiplicata
per 1000, ma non tratteremo questi casi.
Per lo scopo di questo capitolo, i numerali romani vanno
da 1 a 3999.
-
Non c'è modo di rappresentare lo 0 in numeri romani
(Incredibilmente, gli antichi romani non avevano il concetto
di 0 come numero. I numeri servivano a contare quello
che si aveva; come si fa a contare quello che non si ha?).
-
Non c'è modo di rappresentare quantità
negative in numeri romani.
-
Non c'è modo di rappresentare decimali
o frazioni con i numeri romani.
Dato tutto questo, cosa si può chiedere ad una libreria di
funzioni per convertire da numeri romani a numeri arabi e
viceversa?
roman.py requisiti
-
La funzione toRoman dovrebbe restituire la rappresentazione
in numeri romani di qualsiasi numero arabo da 1 a
3999.
-
La funzione toRoman dovrebbe andare in errore per un intero
fuori dall'intervallo da 1 a 3999.
-
La funzione toRoman dovrebbe andare in errore
con un numero non intero.
-
La funzione fromRoman dovrebbe accettare in input un valido
numero romano e restituire il numero arabo corrispondente.
-
La funzione fromRoman dovrebbe andare in errore con un
numero romano non valido.
-
Se si prende un numero arabo, lo si converte in numero romano
e poi lo si riconverte in numero romano, si dovrebbe riavere
il numero di partenza. Vale a dire
fromRoman(toRoman(n)) == n per tutti i
numeri da 1 a 3999.
-
la funzione toRoman dovrebbe sempre restituire un numero
romano formato da lettere maiuscole.
-
La funzione fromRoman dovrebbe accettare solamente numeri
romani (i.e. dovrebbe andare in errore con un input
espresso a lettere minuscole).
Ulteriori letture
-
Questo sito
fornisce ulteriori
informazioni sui numeri romani, incluso un affascinante
resoconto su come i Romani ed
altre civiltà li usavano nella vita reale
(breve resoconto: in modo approssimativo ed inconsistente).