# Zahl-Text Übersetzer



## machinecode (30. Okt 2010)

Hallo Leute!

Ich bin neu hier, mein erstes Post und ich hoffe, dass der Eine oder Andere mir ein bisschen weiterhelfen kann. Ich hab schon ein bisschen rumgestöbert und finde die Seite echt Klasse! 

Also ich habe gerade das 1. Semester and der FH angefangen und wir haben ein paar Aufgaben für Java bekommen. Ich bin seit zwei Wochen dabei. HalloWorld, etc. kennen bestimmt schon einige von euch, war auch alles bis jetzt kein Problem. Einer der Aufgaben die mir Schwierigkeiten gibt, ist einen Übersetzer zu bauen, der ganzzahlige Zahlen zwischen -999 bis 999 in Worten übersetzt, wie neunhundertneunundneunzig. 

Also mit if/else hatte ich guten Erfolg wenn es um einen Schaltjahrrechner geht, aber diese Aufgabe bricht mir gerade das Genick. Hier nochmal die Aufgabenstellung:

_*Ziel ist es, dass Sie die Mehrfachauswahl in der Praxis einsetzen.
Schreiben Sie ein Programm, dass eine ganzzahlige Zahl (zwischen - 999 und 999) einließt
und entsprechend die Zahl als Text wieder ausgibt.*_
_*
Beispiel:
Eingabe: -99
Uebersetzung: minus neunundneunzig*_

Meine Überlegung war, dass man ja eigentlich aus einer Kombination von circa. 20 Variablen eigentlich alle Zahlen darstellen kann. Beispiel:

a - Null
b- ein
c- eins
d- zwei

[...]

zehn
zig
und
hundert
...
etc...

man könnte z.B. die Zahl 854 aus "acht"+"hundert"+"vier"+"und"+"funf"+"zig". Also wie Bausteine die sich austauschen lassen.

Dann hab ich mir überlegt wie ich am schnellsten an die Kombination komme, da fiel mir ein, dass ich mal etwas über ein Algoritmus gehört habe. der z.B. durch Halbierung (Telefonbuch) innerhalb 15 Schritten einen Namen finden kann, aus einen Telefonbuch mit 25,000 Einträgen. Vielleicht kann man mit if und else so etwas aufbauen und dann mit den Variablen kombinieren. 

Beispieleweise.. 
if (Eingabe >999)
    if (Eingabe <999)
      if (eingabe <500)
         if (........)
         else 
     else
else

ich kann zwar schnell auf die Zahl kommen, denn 2000 lässt sich ja in elf Schritten auf eins halbieren, aber wie soll man dann die passenden Wörter einordnen? Ich möchte nur meine Idee damit mitteilen, ich bin sich das es eine Andere und viel leichtere Lösing dafür gibt, aber ich denke der Code wird zwangsweise lang, durch die Übersetzung der Wörter oder nicht? Keine Ahnung.. aber mein Java Wissen ist so limitiert, dass mir etwas besseres nicht einfällt.


Falls jemand ´ne Idee hat, ich würde gerne euren Code studieren, um daraus zu lernen. Ich freue mich schon hier aktiv mitzumachen! Danke.

MC


----------



## a0027301 (30. Okt 2010)

Der " Algoritmus gehört habe. der z.B. durch Halbierung " funktioniert nur, wenn das was Durchsucht werden soll, auch sortiert ist.

Sehe jetzt hier auch keine Anwendung dafür.

Es sind doch folgende Fälle abzudecken

Zahlenwerte bis 12
Zahlenwerte bis 99
Zahlenwerte bis 999
in den letzten beiden Bereichen die 10er bzw. 100er 
sowie minus und plus

Somit ist doch die Eingabe zu untersuchen, ob sie minus oder Plus ist und in welchem Bereich sie liegt. Danach sind die Text zusammen zu bauen.


----------



## A0027301 (30. Okt 2010)

so mal auf die Schnelle


```
public class Main
{
private static HashMap<Integer,String> zahlenwerte=new HashMap<Integer,String>();

public static void main(String[] args)
    {
    zahlenwerte.put(0,"null");
    zahlenwerte.put(1,"ein");
    zahlenwerte.put(2,"zwei");
    zahlenwerte.put(3,"drei");
    zahlenwerte.put(4,"vier");
    zahlenwerte.put(5,"fünf");
    zahlenwerte.put(6,"sechs");
    zahlenwerte.put(7,"sieben");
    zahlenwerte.put(8,"acht");
    zahlenwerte.put(9,"neun");
    zahlenwerte.put(10,"zehn");
    zahlenwerte.put(11,"elf");
    zahlenwerte.put(12,"zwölf");
    zahlenwerte.put(13,"dreizehn");
    zahlenwerte.put(14,"vierzehn");
    zahlenwerte.put(15,"fünfzehn");
    zahlenwerte.put(16,"sechszehn");
    zahlenwerte.put(17,"siebzehn");
    zahlenwerte.put(18,"achtzehn");
    zahlenwerte.put(19,"neunzehn");
    zahlenwerte.put(20,"zwanzig");
    zahlenwerte.put(30,"dreißig");
    zahlenwerte.put(40,"vierzig");
    zahlenwerte.put(50,"fünfzig");
    zahlenwerte.put(60,"sechzig");
    zahlenwerte.put(70,"siebzig");
    zahlenwerte.put(80,"achzig");
    zahlenwerte.put(90,"neunzig");
    zahlenwerte.put(100,"einhundert");
    zahlenwerte.put(200,"zweihundert");
    zahlenwerte.put(300,"dreihundert");
    zahlenwerte.put(400,"vierhundert");
    zahlenwerte.put(500,"fünfhundert");
    zahlenwerte.put(600,"sechshundert");
    zahlenwerte.put(700,"siebenhundert");
    zahlenwerte.put(800,"achthundert");
    zahlenwerte.put(900,"neunhundert");

    for(int i=0;i<1000;i++)
        {
        System.out.println(getText(i));
        }
    }

public static String getText(int zahl)
    {
    if(zahl==1)
        {
        return "eins";
        }
    if(zahl==101)
        {
        return "einhundertundeins";
        }
    if(zahlenwerte.containsKey(zahl))
        {
        return (zahlenwerte.get(zahl));
        }
    if(String.valueOf(zahl).length()==2)
        {
        int einer=Integer.valueOf(String.valueOf(zahl).substring(1,2));
        int zehner=Integer.valueOf(String.valueOf(zahl).substring(0,1));
        return (zahlenwerte.get(einer)+"und"+zahlenwerte.get(zehner*10));
        }
    else
        {
        int einer=Integer.valueOf(String.valueOf(zahl).substring(2,3));
        int zehner=Integer.valueOf(String.valueOf(zahl).substring(1,2));
        int hunderter=Integer.valueOf(String.valueOf(zahl).substring(0,1));
        return (zahlenwerte.get(hunderter*100)+"und"+getText((zehner*10)+einer));
        }
    }

}
```

Das mit Minus und Plus solltest du einbauen können


----------



## machinecode (30. Okt 2010)

A0027301 hat gesagt.:


> so mal auf die Schnelle
> 
> 
> ```
> ...




Danke für deine Mühe, so etwas Schätze ich sehr. Ich werde mir das alles ansehen und versuchen nachzuvollziehen. Es sind viele Befehle drin, die wir noch gar nicht behandelt haben, aber so einen Beispiel so haben wird mir enorm weiterhelfen.

MC


----------



## timbeau (30. Okt 2010)

Ob du es benutzen darfst weiß ich nicht aber eine ziemlich g**** Klasse 


```
import java.text.ParseException;
import java.util.Locale;

import com.ibm.icu.text.*;


public class Number2Word {
    public static void main(String[] args) throws ParseException {
        RuleBasedNumberFormat rbnf = new RuleBasedNumberFormat(Locale.GERMAN, RuleBasedNumberFormat.SPELLOUT);
       String ausgabe = rbnf.format(112.10);
        System.out.println(ausgabe);
        ausgabe = rbnf.format(-89899);
        System.out.println(ausgabe);
        ausgabe = rbnf.format(5367);
        System.out.println(ausgabe);
    }
    
    
}
```
Ausgabe: 

hundertzwölf komma eins
minus neunundachtzigtausendachthundertneunundneunzig
fünftausenddreihundertsiebenundsechzig


----------



## machinecode (30. Okt 2010)

timbeau hat gesagt.:


> Ob du es benutzen darfst weiß ich nicht aber eine ziemlich g**** Klasse
> 
> 
> ```
> ...



Hammer, aber es wird mir nicht sehr viel nützen. Ich muss ja verstehen was ich da codiere, bei deinem Beispiel verstehe ich nur Bahnof teilweise. Ich bin sicher dass ich die meisten Befehle bald lernen werde, die du dort angeben hast. Trotzdem vielen Dank!


----------



## timbeau (30. Okt 2010)

Also worauf es ankommt ist hier nur der import von com.ibm.icu.text.*


Der stellt eben die Klassen RuleBasedNumberFormat zur Verfügung. 

Am Anfang ist es eher wichtig durch deinen Ansatz oben mit Schleifen und Verzweigungen auf die Lösung zu kommen. Dann verstehst du das auch besser. 

Später willst du aber nicht mehr alles selber machen. Ich nehme an, die Leute von IBM(?) haben etwas sehr ähnliches programmiert wie du jetzt machen willst. Nur kann man deren Arbeit durch obigen Import direkt nutzen, das ist ja später auch wirklich praktisch ;-)

Wie weit bist du denn aktuell?


----------



## A0027301 (30. Okt 2010)

"Also worauf es ankommt ist hier nur der import von com.ibm.icu.text.*"

Wir ihm wohl nichts nützen, ohne die Bibliothek dazu. Ohne die kann er importen so viel er will

jars containing the class com.ibm.icu.text.RuleBasedNumberFormat

Davon abgesehen ist das sicher nicht das, was bei der Übung rauskommen sollte


----------



## slawaweis (30. Okt 2010)

machinecode hat gesagt.:


> Dann hab ich mir überlegt wie ich am schnellsten an die Kombination komme, da fiel mir ein, dass ich mal etwas über ein Algoritmus gehört habe. der z.B. durch Halbierung (Telefonbuch) innerhalb 15 Schritten einen Namen finden kann, aus einen Telefonbuch mit 25,000 Einträgen.


das ist die "Binäre Suche", aber hier brauchst Du es nicht.



machinecode hat gesagt.:


> Hammer, aber es wird mir nicht sehr viel nützen. Ich muss ja verstehen was ich da codiere, bei deinem Beispiel verstehe ich nur Bahnof teilweise. Ich bin sicher dass ich die meisten Befehle bald lernen werde, die du dort angeben hast. Trotzdem vielen Dank!


es könnte nützlich sein, als Vergleichbasis. Du könntest deine Implementierung anhand des IBM-Frameworks automatisch testen, ob gleiche Ergebnisse rauskommen.

Der Sinn dieser Aufgabe ist das Prinzip "Teilen und Herrschen" zu verstehen (Divide & Conquer). Der Input des Algorithmus ist zwischen -999 und 999. Das kann man mit Modulo oder über String.valueOf() in einzelne Stellen zerlegen, Beispiel:


```
-999 -> [-][9][9][9]
 523 ->    [5][2][3]
   7 ->          [7]
  -7 ->       [-][7]
```

Um es einfacher zu gestalten, kann man die Ansicht auch umdrehen, d.h. die Eingabe von hinten nach vorne abarbeiten:


```
-999 -> [9][9][9][-]
 523 -> [3][2][5]
   7 -> [7]
  -7 -> [7][-]
```

Jetzt hat man das Problem in höchstens 4 Teilprobleme zerlegt. Alles was bleibt, ist diese Teilprobleme richtig auf die Namen der Zahlen abzubilden, abhängig von deren Position in dem Eingabewert.

Slawa


----------



## Marco13 (31. Okt 2010)

Binäre Suche... Divide and Conquer... eine Riesige Map .... externe Bibliotheken, die genau die Aufgabe lösen, die als Hausaufgabe gestellt wurde... was ist hier eigentlich los? :noe:

Ich nehme an, es geht um ein paar if-Abfragen, vielleict ein switch, und trickreiches % und / - Geschiebe. bei einer positiven dreistelligen Zahl x bekommt man die einzelnen Stellen mit 
einer = x % 10
zehner = (x/10)%10;
hunderter = (x/100)%10
raus. Damit sollte man doch schon was anfangen können....


----------



## A0027301 (31. Okt 2010)

"eine Riesige Map "

???

Irgendwo wirst du die Texte schon ablegen müssen. Und es ist sprachlich ein Unterschied zum Aufbau der Zahlen bis 19, der 10er und 100er sprachweise, sowie der Aussprache der "eins" im Gegensatz zur Aussprache des Einerwertes in den 10er und 100er Bereich.


----------



## timbeau (31. Okt 2010)

@Marco: DU bist schon auf dem richtigen Weg 

Und die Hunderter kannst du z.B. aus den Einern + "hundert" bilden. Wobei nur bei der "Eins" das "s" wegmuss. 

Die Zehner musst du denke ich wirklich in ein Array o.ä. per Hand schreiben.


----------



## Marco13 (31. Okt 2010)

A0027301 hat gesagt.:


> "eine Riesige Map "
> 
> Irgendwo wirst du die Texte schon ablegen müssen. Und es ist sprachlich ein Unterschied zum Aufbau der Zahlen bis 19, der 10er und 100er sprachweise, sowie der Aussprache der "eins" im Gegensatz zur Aussprache des Einerwertes in den 10er und 100er Bereich.



Ich weiß. Wenn man's drauf anlegt braucht man nur ein paar Bruchstücke ("ein", "zwei", "drei"... "zig", "hundert"). Insbesondere kann man ja "einhundert" bis "neunhundert" aus "ein"..."neun" + "hundert" zusammensetzen. 
Das Thema kommt übrigens öfter mal. In dem hier ist noch ein kleiner Fehler, aber es gibt auch noch eine neuere Version hier irgendwo...

EDIT Ach, das hatte timbeau ja schon gesagt. Für die Zehner braucht man die besagten Sonderfälle, aber spätestens wenn das Programm auch Zahlen >1 Trilliarde behandeln soll, sollte man sich was einfallen lassen...


----------

