140 likes | 234 Views
... einhundertdreiundachtzig Kilometer bis. ... eins-acht-drei Kilometer bis. Diese Woche geht es um das Aussprechen von Zahlen. Dazu ein Beispiel . Die freundliche Stimme unseres Auto-Navis sagt nicht: sondern spricht die Zahl so aus wie wir:.
E N D
... einhundertdreiundachtzig Kilometer bis ... ... eins-acht-drei Kilometer bis ... Diese Woche geht es um das Aussprechen von Zahlen. Dazu ein Beispiel. Die freundliche Stimme unseres Auto-Navis sagt nicht: sondern spricht die Zahl so aus wie wir:
Ein „weltraumtaugliches“ Navigationssystem müsste noch viel größere Zahlen aussprechen können, z.B. die Zahl 12 345 678 987 654 321 als zwölf Billiarden dreihundertfünfundvierzig Billionen sechshundertsachtundsiebzig Milliarden neunhundertsiebenundachtzig Millionen sechshundertvierundfünfzig tausend dreihunderteinundzwanzig Das kann eigentlich jeder von uns. Aber: der Teufel steckt wie so oft im Detail! Wir präzisieren die Aufgabenstellung.
Aufgabe: Gegeben eine Zahl x mit 1 x 1024. Erzeuge den Text, wie die Zahl auf Deutsch ausgesprochen wird! Wir gehen davon aus, dass Zahlen dieser Größe in der verwendeten Programmiersprache dargestellt werden können und dass Grundrechenarten wie Plus, Minus, Multiplikation und Division (ganzzahlig mit Rest) zur Verfügung stehen. Wie löst man diese Aufgabe? Wie im Beispiel auf der vorigen Seite teilt man eine Zahl von rechts her immer in Gruppen von je 3 Ziffern auf: Einer, Tausender, Millionen, Milliarden, Billionen, Billiarden, u.s.w.
Eine Zahl lässt sich wie folgt in Dreierzifferngruppen zerlegen (Kommentare in grün): i = -1 while zahl > 0 i += 1 gruppe[i] = zahl % 1000 # Rest zu zahl = zahl / 1000 # Division end Anschließend enthält das Array gruppe die Zifferngruppen: die Einer in gruppe[0], die Tausender in gruppe[1], die Millionen in gruppe[2], die Milliarden in gruppe[3] ... Und in i steht der Index der zuletzt gefundenen Gruppe.
Welche Namen es für große Zahlen gibt und welche Gewichte ihnen entsprechen, kann man im Internet nachlesen unter http://de.wikipedia.org/wiki/Zahlennamen Dort erfährt man z.B., dass auf die Billiarden die Trillionen und Trilliarden folgen und dass eine Oktillion das Gewicht 1048 hat – das ist eine 1 gefolgt von 48 Nullen! Der Rest des Verfahrens besteht nun darin, die Texte zu den Dreiergruppen zu erzeugen, und zwar beginnend mit dem höchsten Gewicht. Wenn wir wissen, wie man den Zahltext zu einer Dreiergruppe erzeugt, dann ist die Aufgabe im Prinzip gelöst. Wenden wir uns also dieser Teilaufgabe zu!
Der Textanteil einer Dreiergruppe ist leer, wenn die Dreiergruppe den Wert 0 hat. Das zeigt ein Beispiel: 1 000 111 ergibt eine Million einhundertelf Ansonsten zerlegt man die Dreiergruppe in Ihre Bestandteile: h = zahl / 100 # Die erste Ziffer r = zahl % 100 # Der Rest r wird aufgespaltet in z = r / 10 # die zweite Ziffer und rr = r % 10 # die dritte Ziffer Spätestens an dieser Stelle muss man den Text zu jeder Ziffer kennen, um ihn ausgeben zu können.
Wir verwenden dazu ein Array von Strings,in dem nicht nur die Zifferntexte, sondern gleich auch noch die Texte der Zahlen 10 bis 19 eingetragen sind: kleiner20 = [ "Null", "ein", "zwei", "drei", "vier", "fuenf", "sechs", "sieben", "acht", "neun", "zehn", "elf", "zwoelf", "dreizehn", "vierzehn", "fuenfzehn", "sechzehn", "siebzehn", "achtzehn", "neunzehn"] In einem zweiten Array von Strings halten wir die Texte zu den Vielfachen von 10, wobei stets zehner[i] der Text zu i*10 ist (Arrayindizes beginnen bei 0): zehner = [ "Null", "zehn", "zwanzig", "dreissig", "vierzig", "fuenfzig", "sechzig", "siebzig", "achtzig", "neunzig"]
Wir kommen nun zum Kern des Verfahrens, bei dem der Text einer Dreiergruppe in der Variablen erg aufgesammelt wird: • erg ist anfangs leer. • Zuerst wird die Hunderterstelle angefügt, dann der Rest (Text anfügen kann man mit "+" bzw. "+="). • Ist der Rest < 20, dann entnimmt man den Text direkt dem Array kleiner20. • Andernfalls fügt man an: Einerstelle - "und" - Zehnerstelle • Beachte, dass fast alles fehlen kann! • Das "und" wird nur gebraucht, um Einer und Zehner zu verbinden, wenn beide vorhanden sind.
Die Umwandlung einer Dreiergruppe in einen Text geht also nach der Zerlegung in h, r, z und rr wie folgt weiter: erg = "" #Text zunächst leer # vorhandene Hunderter anfügen: if h > 0 then erg += kleiner20[h] + "hundert"; end # den Rest kleiner 100 umwandeln: if r > 0 then # falls es diesen Rest überhaupt gibt if r < 20 then # Einfache Behandlung von kleinen Zahlen erg += kleiner20[r] else # wenn 10er oder 1er fehlen, dann kein "und"! if rr > 0 then erg += kleiner20[rr] ; end # Einer if rr > 0 and z > 0 then erg += "und"; end # "und" if z > 0 then erg += zehner[z]; end # Zehner end end
Wandeln wir nach diesem Verfahren dreistellige Zahlen um, dann ergibt sich für viele Zahlen das gewünschte Resultat in erg: • Für 111 ergibt sich "einhundertelf" • Für 627 ergibt sich "sechshundertsiebenundzwanzig" • Für 308 ergibt sich "dreihundertacht" • In einigen Fällen ist das Resultat noch unbefriedigend: • Für 1 ergibt sich "ein" • Für 901 ergibt sich "neunhundertein"
Tatsächlich gibt es immer dann Probleme, wenn die Dreier-gruppe mit "01" endet. Die naheliegende Reparatur, in dem Array kleiner20 den String "ein" durch "eins" zu ersetzen, funktioniert leider nicht: • Z.B. für 41 ergäbe sich dann nämlich "einsundvierzig" • Noch mehr Fälle sind bezüglich der Endziffer 1 bei großen Zahlen zu berücksichtigen. Wir sagen ja: • "eintausend" für 1 000 • "eine Million" für 1 000 000 • "neunhunderteins Millionen" für 901 000 000
Die Lösung besteht aus zwei Maßnahmen: • In Dreiergruppen unterscheidet man zwischen Singular (für die 1) und Plural (für größere Zahlen wie 901). • Die Anhänge an die Dreiergruppe unterscheiden sich je nach dem, ob Singular oder Plural vorliegt und in welcher Dreiergruppe (Einer, Tausender, Millionen) wir sind: • "eins" und "neunhunderteins" • "eintausend" und "neunhunderteinstausend" • "eineMillion" und "neunhunderteins Millionen"
Für die Anhänge verwenden dazu zwei Arrays von Strings mit den auf der vorigen Seite grün geschriebenen Anhängen: singular = ["s", "tausend", "e Million", "e Milliarde", … "e Trilliarde"] plural = [ "", " tausend ", "Millionen", "Milliarden", … "Trilliarden"] Damit kann man das Programm von S. 4 wie folgt fortsetzen: erg = "" while i >= 0 erg += sprichDreier(gruppe[i], singular[i], plural[i]) + " " i -= 1 end Danach enthält erg die "Zahl, wie man sie spricht"!
Das komplette Programm findet ihr auf meiner Homepage In Pascal sind Zahldarstellungen (wie in den meisten anderen Sprachen) beschränkt; auch das Stringhandling ist wenig komfortabel. Ich habe daher das Programm in der für diese Zwecke wesentlich günstigeren Skriptsprache Ruby verfasst. Wenn ihr das Programm ausprobieren wollt, müsst ihr euch den Ruby-one-click-installer und die Mondrian-IDE dazu herunterladen. Viel Spaß wünscht Lothar Schmitz!