[successivo]
[precedente]
[inizio]
[fine]
[indice generale]
[indice ridotto]
[translators]
[docinfo]
[indice analitico]
[volume]
[parte]
Capitolo 631. Trasformazione in lettere
Nell'ambito della realizzazione di applicativi gestionali, capitano frequentemente problemi di conversione di numeri interi in una qualche forma alfabetica. In questo capitolo vengono mostrati degli algoritmi molto semplici per risolvere questo tipo di problemi.
631.1
Da numero a sequenza alfabetica pura
Esiste un tipo di numerazione in cui si utilizzano solo le lettere dell'alfabeto, dalla «a» alla «z», senza accenti o altri simboli speciali, senza distinguere tra maiuscole e minuscole. In generale, i simboli da «a» a «z» consentono di rappresentare valori da 1 a 26, dove lo zero è escluso. Per rappresentare valori superiori, si possono accoppiare più lettere, ma il calcolo non è banale, proprio perché manca lo zero.
Attraverso la pseudocodifica introdotta nel capitolo 421, si può descrivere una funzione che calcoli la stringa corrispondente a un numero intero positivo, maggiore di zero. Per prima cosa, occorre definire una sotto funzione che sia in grado di trasformare un numero intero, compreso tra 1 e 26 nella lettera alfabetica corrispondente; ciò si ottiene abbastanza facilmente, attraverso la verifica di più condizioni in cascata. Il vero problema, purtroppo, sta nel costruire una stringa composta da più lettere, quando si vuole rappresentare un valore superiore a 26. Non essendoci lo zero, diventa difficile fare i calcoli. Se si parte dal presupposto che il numero da convertire non possa essere superiore a 702, si sa con certezza che servono al massimo due lettere alfabetiche (perché la stringa «ZZ» corrisponderebbe proprio al numero 702); in tal caso, è sufficiente dividere il numero per 26, dove la parte intera rappresenta la prima lettera, mentre il resto rappresenta la seconda. Tuttavia, se la divisione non dà resto, la stringa corretta è quella precedente. Per esempio, il numero 53 corrisponde alla stringa «BA», perché 53/26 = 2 con un resto di 1. Nello stesso modo, però, 52 si traduce nella stringa «AZ», perché 53/26 = 2, ma non c'è resto, pertanto, «B_» diventa «AZ».
La pseudocodifica seguente riepiloga il concetto in modo semplificato, dove, a seconda delle esigenze, la conversione è sempre limitata a un valore massimo. Le omissioni sono parti di codice facilmente intuibili.
INTEGER_TO_ALPHABET (N)
ALPHABET_DIGIT (DIGIT)
IF DIGIT = 0
THEN
RETURN ""
ELSE IF DIGIT = 1
THEN
RETURN "A"
ELSE IF DIGIT = 2
THEN
RETURN "B"
...
...
ELSE IF DIGIT = 26
THEN
RETURN "Z"
ELSE
RETURN "##ERROR##"
FI
END ALPHABET_DIGIT
IF N <= 0
THEN
RETURN "##ERROR##";
ELSE IF N <= 26
THEN
RETURN ALPHABET_DIGIT (N)
ELSE IF N <= 52
THEN
N := N - 52
RETURN "A" ALPHABET_DIGIT (N)
ELSE IF N <= 78
THEN
N := N - 78
RETURN "B" ALPHABET_DIGIT (N)
...
...
ELSE IF N <= 702
THEN
N := N - 702
RETURN "Z" ALPHABET_DIGIT (N)
ELSE IF N <= 728
THEN
N := N - 728
RETURN "AA" ALPHABET_DIGIT (N)
ELSE IF N <= 754
THEN
N := N - 754
RETURN "AB" ALPHABET_DIGIT (N)
...
...
ELSE
RETURN "##ERROR##"
END IF
END INTEGER_TO_ALPHABET
|
|
631.2
Da numero a numero romano
La conversione di un numero intero positivo in una stringa che rappresenta un numero romano, ha un discreto livello di difficoltà, perché la numerazione romana non prevede lo zero, perché la tecnica prevede la somma e la sottrazione di simboli (a seconda della posizione) e poi perché diventa difficile indicare valori multipli delle migliaia.
Per prima cosa è necessario conoscere il valore associato ai simboli elementari:
Simbolo | Valore corrispondente |
I | 1 |
V | 5 |
X | 10 |
L | 50 |
C | 100 |
D | 500 |
M | 1 000 |
|
Un simbolo posto alla destra di un altro simbolo con un valore maggiore o uguale di questo, viene sommato; al contrario, un simbolo posto alla sinistra di un altro simbolo con un valore maggiore di questo, viene sottratto. Per esempio, «VI» equivale a 5+1, mentre «IV» equivale a 5-1. Esistono comunque anche altri vincoli, per evitare di creare numeri difficili da interpretare a causa di una complessità di calcolo eccessiva.
Per risolvere il problema con un algoritmo relativamente semplice, si può scomporre il valore di partenza in fasce: unità, decine, centinaia e migliaia (la conversione di valori superiori genererebbe soltanto una serie lunghissima di «M» che risulta poi troppo difficile da leggere).
INTEGER_TO_ROMAN (N)
LOCAL DIGIT_1 INTEGER
LOCAL DIGIT_2 INTEGER
LOCAL DIGIT_3 INTEGER
LOCAL DIGIT_4 INTEGER
DIGIT_1 := 0
DIGIT_2 := 0
DIGIT_3 := 0
DIGIT_4 := 0
DIGIT_1_TO_ROMAN (DIGIT)
IF DIGIT = 0
THEN
RETURN ""
ELSE IF DIGIT = 1
THEN
RETURN "I"
ELSE IF DIGIT = 2
THEN
RETURN "II"
ELSE IF DIGIT = 3
THEN
RETURN "III"
ELSE IF DIGIT = 4
THEN
RETURN "IV"
ELSE IF DIGIT = 5
THEN
RETURN "V"
ELSE IF DIGIT = 6
THEN
RETURN "VI"
ELSE IF DIGIT = 7
THEN
RETURN "VII"
ELSE IF DIGIT = 8
THEN
RETURN "VIII"
ELSE IF DIGIT = 9
THEN
RETURN "IX"
END IF
END DIGIT_1_TO_ROMAN
DIGIT_2_TO_ROMAN (DIGIT)
IF DIGIT = 0
THEN
RETURN ""
ELSE IF DIGIT = 1
THEN
RETURN "X"
ELSE IF DIGIT = 2
THEN
RETURN "XX"
ELSE IF DIGIT = 3
THEN
RETURN "XXX"
ELSE IF DIGIT = 4
THEN
RETURN "XL"
ELSE IF DIGIT = 5
THEN
RETURN "L"
ELSE IF DIGIT = 6
THEN
RETURN "LX"
ELSE IF DIGIT = 6
THEN
RETURN "LXX"
ELSE IF DIGIT = 8
THEN
RETURN "LXXX"
ELSE IF DIGIT = 9
THEN
RETURN "XC"
END IF
END DIGIT_2_TO_ROMAN
DIGIT_3_TO_ROMAN (DIGIT)
IF DIGIT = 0
THEN
RETURN ""
ELSE IF DIGIT = 1
THEN
RETURN "C"
ELSE IF DIGIT = 2
THEN
RETURN "CC"
ELSE IF DIGIT = 3
THEN
RETURN "CCC"
ELSE IF DIGIT = 4
THEN
RETURN "CD"
ELSE IF DIGIT = 5
THEN
RETURN "D"
ELSE IF DIGIT = 6
THEN
RETURN "DC"
ELSE IF DIGIT = 7
THEN
RETURN "DCC"
ELSE IF DIGIT = 8
THEN
RETURN "DCCC"
ELSE IF DIGIT = 9
THEN
RETURN "CM"
END IF
END DIGIT_3_TO_ROMAN
DIGIT_4_TO_ROMAN (DIGIT)
IF DIGIT = 0
THEN
RETURN ""
ELSE IF DIGIT = 1
THEN
RETURN "M"
ELSE IF DIGIT = 2
THEN
RETURN "MM"
ELSE IF DIGIT = 3
THEN
RETURN "MMM"
ELSE IF DIGIT = 4
THEN
RETURN "MMMM"
ELSE IF DIGIT = 5
THEN
RETURN "MMMMM"
ELSE IF DIGIT = 6
THEN
RETURN "MMMMMM"
ELSE IF DIGIT = 7
THEN
RETURN "MMMMMMM"
ELSE IF DIGIT = 8
THEN
RETURN "MMMMMMMM"
ELSE IF DIGIT = 9
THEN
RETURN "MMMMMMMMM"
END IF
END DIGIT_4_TO_ROMAN
DIGIT_4 := int (N/1000)
N := N - (DIGIT_4 * 1000)
DIGIT_3 := int (N/100)
N := N - (DIGIT_3 * 100)
DIGIT_2 := int (N/10)
N := N - (DIGIT_2 * 10)
DIGIT_1 := N
RETURN DIGIT_4_TO_ROMAN (DIGIT_4)
DIGIT_3_TO_ROMAN (DIGIT_3)
DIGIT_2_TO_ROMAN (DIGIT_2)
DIGIT_1_TO_ROMAN (DIGIT_2)
END INTEGER_TO_ROMAN
|
|
Come si vede, dopo aver scomposto il valore in quattro fasce, si utilizzano quattro funzioni distinte per ottenere la porzione di stringa che traduce il valore relativo. L'istruzione RETURN finale intende concatenare tutte le stringhe risultanti.
631.3
Da numero a lettere, nel senso verbale
Quando si trasforma un numero in lettere, per esempio quando si vuole trasformare 123 in «centoventitre», l'algoritmo di conversione deve tenere conto delle convenzioni linguistiche e non esiste una soluzione generale per tutte le lingue.
Per quanto riguarda la lingua italiana, esistono nomi diversi fino al 19, poi ci sono delle particolarità per i plurali o i singolari. La pseudocodifica seguente risolve il problema in una sola funzione ricorsiva. Le omissioni dovrebbero essere sufficientemente intuitive.
INTEGER_TO_ITALIAN (N)
LOCAL X INTEGER
LOCAL Y INTEGER
IF N = 0
THEN
RETURN ""
ELSE IF N = 1
THEN
RETURN "UNO"
ELSE IF N = 2
THEN
RETURN "DUE"
ELSE IF N = 3
THEN
RETURN "TRE"
ELSE IF N = 4
THEN
RETURN "QUATTRO"
ELSE IF N = 5
THEN
RETURN "CINQUE"
ELSE IF N = 6
THEN
RETURN "SEI"
ELSE IF N = 7
THEN
RETURN "SETTE"
ELSE IF N = 8
THEN
RETURN "OTTO"
ELSE IF N = 9
THEN
RETURN "NOVE"
ELSE IF N = 10
THEN
RETURN "DIECI"
ELSE IF N = 11
THEN
RETURN "UNDICI"
ELSE IF N = 12
THEN
RETURN "DODICI"
ELSE IF N = 13
THEN
RETURN "TREDICI"
ELSE IF N = 14
THEN
RETURN "QUATTORDICI"
ELSE IF N = 15
THEN
RETURN "QUINDICI"
ELSE IF N = 16
THEN
RETURN "SEDICI"
ELSE IF N = 17
THEN
RETURN "DICIASSETTE"
ELSE IF N = 18
THEN
RETURN "DICIOTTO"
ELSE IF N = 19
THEN
RETURN "DICIANNOVE"
ELSE IF N = 20
THEN
RETURN "VENTI"
ELSE IF N = 21
THEN
RETURN "VENTUNO"
ELSE IF (N >= 22) AND (N <= 29)
THEN
RETURN "VENTI" INTEGER_TO_ITALIAN (N-20)
ELSE IF N = 30
THEN
RETURN "TRENTA"
ELSE IF N = 31
THEN
RETURN "TRENTUNO"
ELSE IF (N >= 32) AND (N <= 39)
THEN
RETURN "TRENTA" INTEGER_TO_ITALIAN (N-30)
...
...
ELSE IF N = 90
THEN
RETURN "NOVANTA"
ELSE IF N = 91
THEN
RETURN "NOVANTUNO"
ELSE IF (N >= 92) AND (N <= 99)
THEN
RETURN "NOVANTA" INTEGER_TO_ITALIAN (N-90)
ELSE IF (N >= 100) AND (N <= 199)
THEN
RETURN "CENTO" INTEGER_TO_ITALIAN (N-100)
ELSE IF (N >= 200) AND (N <= 999)
THEN
X := int (N / 100)
Y := N - (X * 100)
RETURN INTEGER_TO_ITALIAN (X)
"CENTO"
INTEGER_TO_ITALIAN (Y)
ELSE IF (N >= 1000) AND (N <= 1999)
THEN
RETURN "MILLE" INTEGER_TO_ITALIAN (N-1000)
ELSE IF (N >= 2000) AND (N <= 999999)
THEN
X := int (N / 1000)
Y := N - (X * 1000)
RETURN INTEGER_TO_ITALIAN (X)
"MILA"
INTEGER_TO_ITALIAN (Y)
ELSE IF (N >= 1000000) AND (N <= 1999999)
THEN
RETURN "UNMILIONE" INTEGER_TO_ITALIAN (N-1000000)
ELSE IF (N >= 2000000) AND (N <= 999999999)
THEN
X := int (N / 1000000)
Y := N - (X * 1000000)
RETURN INTEGER_TO_ITALIAN (X)
"MILIONI"
INTEGER_TO_ITALIAN (Y)
ELSE IF (N >= 1000000000) AND (N <= 1999999999)
THEN
RETURN "UNMILIARDO" INTEGER_TO_ITALIAN (N-1000000000)
ELSE IF (N >= 2000000000) AND (N <= 999999999999)
THEN
X := int (N / 1000000000)
Y := N - (X * 1000000000)
RETURN INTEGER_TO_ITALIAN (X)
"MILIARDI"
INTEGER_TO_ITALIAN (Y)
ELSE
"##ERROR##"
END IF
END INTEGER_TO_ITALIAN
|
|
Appunti di informatica libera 2006.07.01 --- Copyright © 2000-2006 Daniele Giacomini -- <daniele (ad) swlibero·org>
Dovrebbe essere possibile fare riferimento a questa pagina anche con il nome trasformazione_in_lettere.htm
[successivo]
[precedente]
[inizio]
[fine]
[indice generale]
[indice ridotto]
[translators]
[docinfo]
[indice analitico]