Beispiel 5 - Zahlen in Strings konvertieren


... [ Seminar "Haskell" ] ... [ Inhaltsverzeichnis ] ... [ zurück ] ... [ weiter ] ...

Übersicht: Beispiel 5 - Zahlen in Strings konvertieren


Einleitung

Ziel dieses letzten Beispieles soll die Umwandlung einer Zahl in eine umgangssprachliche Zeichenkettendarstellung sein. Diese Aufgabe kann nur für endliche Zahlenbereiche gelöst werden, da für die verschiedenen Größenordnungen jeweils verschiedene (unberechenbare) Bezeichnungen (zehn, hundert, tausend, usw.) zum Einsatz kommen. Die Lösung wird ein bottom-up-Entwurf sein, der das Problem zuerst für sehr einfache Zahlen löst (1-99) und nachfolgend dann diese Lösung in eine Variante für den Bereich von 100-999 einbettet usw.


[ nach oben ]

Zahlen von 1-99

Die Umwandlung für die Zahlen von 1-99 wird von der Funktion convert2 (2 für maximal 2 Stellen) geleistet. Zuerst wird die Zahl in ihre zwei Stellen zerlegt (1er und 10er Stelle) und das Ergebnis in einem Tupel übergeben (digits). Der Einsatz der combine-Funktion auf diesem Tupel errechnet nun die fertige Zeichenkette durch Fallunterscheidung und indizierten Zugriff in Listen vorgefertigter Wörter. Die 1 wird separat behandelt, da sie lediglich alleine "Eins" lautet, ansonsten nur "Ein" wie bei "Einhundert" (Fall (0,1)). Die einstelligen Zahlen >1 (Zwei, Drei usw.) werden direkt in einen entsprechenden Listenzugriff (Fall (0,u+1), Liste units) überführt. Die Zahlen von 10 bis 19 sind Sonderfälle und werden ebenfalls direkt in eine eigene Liste abgebildet (Fall (1,u), Liste teens). Für alle größeren Zahlen wird unterschieden zwischen solchen mit einer Ziffer > 0 auf der ersten Stelle (t+2,u+1) und solchen ohne (t+2,0). Im ersteren Fall werden Zugriffe auf die Listen tens und units kombiniert, um letzteren wird lediglich in die tens-Liste indiziert.

01 -- units sind die einfachen Zahlen, teens sind die Sonder-zahlen von 10 bis 19 und tens sind die Vielfachen von 10
02 units,teens,tens :: [String]
03 units = ["Ein","Zwei","Drei","Vier","Fuenf","Sechs","Sieben","Acht", "Neun"]
04 teens = ["Zehn","Elf","Zwoelf","Dreizehn","Vierzehn","Fuenfzehn","Sechszehn","Siebzehn","Achtzehn","Neunzehn"]
05 tens = ["Zwanzig","Dreißig","Vierzig","Fuenfzig","Sechzig","Siebzig","Achtzig","Neunzig"]
5-1.txt

Codebeispiel 46

01 -- Konvertieren einer zweistelligen Zahl in einen String
02 convert2 :: Int -> String
03 convert2 = combine2 . digits2
04 
05 -- Aufteilen einer Zahl in den /10 teilbaren Anteil und Rest
06 digits2 :: Int -> (Int,Int)
07 digits2 n = (n `div` 10,n `mod` 10)
08 
09 -- Fallabhängig in die String-Listen indizieren
10 combine2 :: (Int,Int) -> String
11 combine2 (0,1)     = "Eins"
12 combine2 (0,u+1)   = units!!u
13 combine2 (1,u)     = teens!!u
14 combine2 (t+2,0)   = tens!!t
15 combine2 (t+2,u+1) = units!!u ++ "und" ++ tens!!t
5-2.txt

Codebeispiel 47



[ nach oben ]

Zahlen von 1-999

Die Definition der nächsthöheren Konvertierungsfunktion convert3 (Zahlen 1-999, dreistellig) greift wie oben bereits angekündigt auf die Funktion convert2 zurück. Sie zerlegt die Zahl in ihre 100er-Stelle und den Rest. Ist die 100er-Stelle == 0 und der Rest != 0 (0,t+1), so wird die Umwandlung vollständig an die convert2-Funktion deligiert. Existiert lediglich die 100er-Stelle (h+1,0), so wird diese über die units-Liste in einen String umgewandelt. Im Fall (h+1,t+1) existieren sowohl 100er-Stelle als auch Rest und die vorgenannten Funktionen werden kombiniert.

01 -- Konvertieren einer dreistelligen Zahl in einen String
02 convert3 :: Int -> String
03 convert3 = combine3 . digits3
04 
05 -- Aufteilen einer Zahl in den /100 teilbaren Anteil und Rest 
06 digits3 :: Int -> (Int,Int)
07 digits3 n = (n `div` 100,n `mod` 100)
08 
09 -- Fallabhängig in die String-Listen indizieren
10 combine3 :: (Int,Int) -> String
11 combine3 (0,t+1)   = convert2 (t+1)
12 combine3 (h+1,0)   = units!!h ++ "hundert"
13 combine3 (h+1,t+1) = units!!h ++ "hundert und " ++ convert2 (t+1)
5-3.txt

Codebeispiel 48



[ nach oben ]

Zahlen von 1-999.999

Die Einbeziehung von Tausendern verläuft analog zu convert3, die Zahl wird in ihren Tausenderanteil und den Rest aufgeteilt, die Berechnung der Zeichenfolge für den Rest wird gegebenenfalls an convert3 deligiert. Ein Sonderfall muß für das "und" zwischen der letzten und der vorletzten Zahl eingeführt werden, ist der Rest < 100, so muß das "und" von convert6 selber erzeugt werden (da im Anschluß das letzte Wort folgen wird), ansonsten wird diese Aufgabe implizit an convert3 deligiert.

01 convert 6 -- Konvertieren einer sechsstelligen Zahl
02 
03 -- Aufteilen in den /1000 teilbaren Anteil und Rest 
04 digits6 :: Int -> (Int,Int)
05 digits6 n = (n `div` 1000,n `mod` 1000)
06 
07 -- Fallabhängig in die String-Listen indizieren 
08 combine6 :: (Int,Int) -> String
09 combine6 (0,h+1)   = convert3 (h+1)
10 combine6 (m+1,0)   = convert3 (m+1) ++ "tausend"
11 combine6 (m+1,h+1) = convert3 (m+1) ++ "tausend" ++ link (h+1) ++ convert3 (h+1)
12 
13 link :: Int -> String
14 link h = if h < 100 then " und " else " "
15 
5-4.txt

Codebeispiel 49


... [ Seminar "Haskell" ] ... [ Inhaltsverzeichnis ] ... [ zurück ] ... [ weiter ] ... [ nach oben ] ...

valid html4 logo Code generated with AusarbeitungGenerator Version 1.1, weblink