# Taschenrechner mit neuem Datentyp



## hanswurst (2. Jun 2009)

Hi!
Ich hoffe ich bin hier richtig und der Titel passt auch irgendwie.... (Vielleicht dioch besser ins anfänger forum?!)
Und ich hoffe ebenfalls, dass ich hier mit solchen Fragen niemand auf die nerven gehe. Denke das (Taschenrechner) wurde schon desöfteren gefragt aber ich habe spezielle Probleme beim Programmieren an denen es bei mir hakt und hoffe ihr könnt mir damit helfen 
Also ich soll einen Taschenrechner in Java Programmieren der + und - rechnen kann.
Allerdings soll ich dafür einen neuen Datentyp entwickeln, der die Eingabe die als String eingelesen werden soll in Exponentialschreibweise "umformt".

Die Eingabe habe ich. Die Methodenköpfe sind alle so vorgegeben bis auf die Klasse mit der ich den neuen Datentypen bastele.

Jetzt meine Fragen:
Ich denke ich muss den neuen Datentypen doch irgendwie als ein Array gebastelt kriegen, das sehe ich ja an den eckigen Klammern [] bei dem Rückgabewert der "eingabe"-Methode. Wie krieg ich das denn genau hin?
Der neue Datentyp "Zahl" soll aus 2 Integern bestehen, deshalb habe ich angenommen, dass ein Int-Wert die Basis und der andere der negative Exponent der Exponentialdarstellung werden soll.
Die Basis ist einfach der übergebene String ohne das "," und der negative Exponent die Anzahl der Stellen hinter dem Komma. Das dürfte ich ja irgendwie wieder mit nem matcher und split etc hinkriegen - das sehe ich nicht so als Problem.
Dann könnte ich doch den Exponent der einen Zahl zum Beispiel so kriegen z1.Zahl[1] und die Basis z1.Zahl[2]
So stelle ich mir das jedenfalls vor - vielleicht bin ich auch total auf dem Holzweg. Dann wäre addieren und subtrahieren der Zahlen auch kein problem mehr soweit ich das überblicken kann.
Nur fehlt mir der Weg dahin bzw der Weg zu dem neuen Datentyp.

Ich muss da doch auch mit Klassenvariablen arbeiten, richtig? Brauche ich irgendwelche Konstruktoren oder ist die Klasse mit der ich den neuen Datentyp erstellen soll quasi der Konstruktor?!

Vielleicht kann mir ja jemand sagen ob ich auf dem richtigen Weg bin und mir einen anstubser zu dem Datentyp-Problem geben. 
(Habe die Suche schon benutzt und was gefunden aber ich bin nicht wirklich schlauer daraus geworden)
Danke im vorraus.

Euer hanswurst

import java.io.*;
import java.util.regex.*;


```
/**
 *
 * @author hanswurst
 */
public class RechnerTest {

    // Operanden werden als Klassenvariablen initialisiert?!
    static z1;
    static z2;

    // neuer Datentyp mit 2 int als Grunddatentypen
    // Bsp: aus 1,234 soll 1234*10^-3 werden
    // Anzahl der Stellen hinter dem Komma ist negativer Exponent
    public Zahl[] (String[]) {
        int basis = 0;
        int exponent = 0;
    }

    // Zahl als String einlesen
    // Es soll kein "." als Komma genutzt werden sondern ein ","
    public Zahl[] eingabe() throws IOException {
        // BufferedReader Konsoleneingabe
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String s;
        System.out.println("Bitte geben Sie eine Zahl ein:");
        s = br.readLine();
        System.out.println(s);
        // Nur Zahlen der Form "Zahl1,Zahl2" sind erlaubt, Zahl2 ist nicht zwingend erforderlich
        Pattern p = Pattern.compile("[0-9]+,?[0-9]*");
        Matcher m = p.matcher(s);
        if (m.matches() == true) {
            System.out.println("Eingabe erfolgreich!");
        } else {
            System.out.println("Keine gueltige Eingabe! (Bsp für Eingabe : 1,25)");
        }
    }

    /*
    // Zahl addieren
    Zahl add(Zahl add[]) {
    
    }
    
    
    // Zahl subtrahieren
    Zahl sub(Zahl sub[]) {
    
    }
    
    
    // Ergebnis ausgeben
    void ausgabe(Zahl erg) {
    
    }
     */
    
    public static void main(String args[]) {

    }
}
```


----------



## Landei (2. Jun 2009)

Keine Ahnung, was da die [] sollen. Offenbar brauchst du eine neue Klasse Zahl.

(ungetestet)

```
public class Zahl {
   private final int basis;
   private final int exponent;

   public Zahl(int basis, int exponent) {
     this.basis = basis;
     this.exponent = exponent;
   }

   public Zahl(String str) {
       int comma = str.indexOf(",");
       if (comma == -1) {
          basis = Integer.parseInt(str);
          exponent = 0;
       } else {
          basis = Integer.parseInt(str.substring(0, comma) + str.substring(comma+1));
          exponent = str.length - comma - 1; //oder so
       }
   }

   public int getBasis() { return basis; }
   public int getExponent() { return exponent; }

   public Zahl add(Zahl that) {
       public int newExponent = Math.max(this.exponent, that.exponent);
       int b1 = this.basis;
       for(int i = 1; i < newExponent - this.exponent; i++) {
          b1 *= 10;
       } 
       int b2 = that.basis
       for(int i = 1; i < newExponent - that.exponent; i++) {
          b2 *= 10;
       }
       return new Zahl(b1 + b2, newExponent); 
   }
   //usw.
}
```


----------



## Michael... (2. Jun 2009)

Mal abgesehen, dass Dein Code so nicht kompilierbar ist. Soll das der Taschenrechner sein, oder die Klasse der Exponentialzahl?
Dient die neue Klasse nur der Darstellung oder soll dann mit Ihr auch gerechnet werden?


----------



## Landei (2. Jun 2009)

Nur die Darstellung der Zahl. Oder würdest du deinen Taschenrechner "Zahl" nennen? "Graf Zahl" ginge ja vielleicht noch an, wenn er beim Rechnen lachen würde... 

Ich hab das aus'm Kopp getippt, da kann man schonmal die Klammern bei str.lenght() und so vergessen (deshalb steht ja auch *"ungetestet"* drüber).


----------



## Michael... (2. Jun 2009)

Mein Kommentar bezog sich auf den Post von hanswurst. Du bist quasi dazwischengerutscht.


----------



## Landei (2. Jun 2009)

LOL


----------



## hanswurst (2. Jun 2009)

Michael... hat gesagt.:


> Mein Kommentar bezog sich auf den Post von hanswurst. Du bist quasi dazwischengerutscht.



Jo ist mir klar, dass das so noch nicht kompiliert werden kann - ist ja auch nur mein erster Ansatz und da ist halt noch nicht viel drin ausser die Eingabe einer Zahl über die Konsole.
Eigentlich dachte ich, ich könnte die ganze Aufgabe in eine Taschenrechner Klasse schreiben. 
Aber das ist wohl der falsche Ansatz weil nicht Ojektorientiert, etc?!
Vielleicht nur die Konstruktoren,Methoden und so in eine Klasse Rechner und dann eine Klasse RechnerTest über die man die Eingabe macht?!

Die neue Klasse soll der Darstellung dienen und dann sollen eben auch 2 solcher Zahlen von diesem Datentyp miteinander addiert oder voneinander subtrahiert werden können.

Aus 1,2345 soll zum Beispiel das Konstrukt 1234*10^{-4} werden und weil hier ein Konstrukt verlangt wird, muss man das wohl mit einem neuen Datentypen machen. (Hierzu ist der Tip gegeben, das man sich anschauen soll was Klassenvariablen sind).
Was ein konstruktor ist weis ich, und so wie es das nette landei gepostet hat, hätte ich mir das eigentlich auch gedacht weil wir das bisjetzt immer so gemacht haben, nur ich habe (wie er) 



Landei hat gesagt.:


> Keine Ahnung, was da die [] sollen.



und die Methodenköpfe waren halt so vorgegeben weshalb ich das wahrscheinlich auch so zum laufen kriegen soll.
Naja ich rätsel noch ein bsischen und werde morgen nochmal die möglichkeit haben da nachzufragen aber wenn von euch jemand noch eine Idee hat dann immer her damit 


hanswurst


----------



## Darksideone (2. Jun 2009)

Hi, ich hab da eine ganz ähnliche Aufgabe, kenne mich aber in java noch nicht aus. Der Java-Einstieg ist recht mühselig.

...
Sie sollen einen eigenen Taschenrechner entwerfen. Dieser soll zwei Zahlen einlesen und sie danach entweder addieren oder subtrahieren. Hierbei ist aber darauf hinzuweisen, dass Sie keine Variablen des Typs Integer, Double oder Float sondern Strings einlesen sollen. Hierbei soll es egal sein ob ein Komma in der Zahl vorhanden ist oder nicht.

Im Falle das über den String eine Gleitkommazahl eingelesen wird, sollen Sie diese mit Hilfe der Exponentialdarstellung verarbeiten.
Bei der Ausgabe soll ein normale Kommazahl ausgegeben werden. Das hat zur Folge, dass Sie den Datentyp wieder zurück konvertieren müssen.

Dabei ist mein Hauptproblem, zu schauen wo das Komma im String liegt (wieviele Nachkommastellen vorhanden sind), um es als (negativen) Exponent zu schreiben.
(wohl am einfachsten in 2 Variablen, für Zahl und Exponent).
-Darauf ist ja Landei eingegangen,...
Irgendwie finde ich recht wenig sinnvolles (Beispiele, Hilfen,...), was gut auf den Umgang mit Strings eingeht.

Das nächste Problem besteht dann darin, diese Exponenten zu verrechnen.
Habe mir dazu noch nicht viele Gedanken gemacht.
Überlegung:
4*10^-4 = 4/10^4 =0,0004
ist nur die Frage, wie man hoch 4 in java elegant hin bekommt (wohl mit 10*10*10*10, aber das in z.B. einer Schleife dürfte auch nicht so toll sein,...)


naja, ka, werde mir noch Gedanken machen, Bücher lesen und weiter suchen...
wird ne lange Nacht...


----------



## Darksideone (2. Jun 2009)

So, hab mir noch bissel was zum Verrechnen überlegt.
Die "keine Überlegung" davor war natürlich blödsin.
Viel komfortabler sollte es folgender maßen zu berechnen sein.

Der String zahl1 z.B. 4,123 wird zerlegt in 4123*10^-3, daraus bekommt man 4123 (z.B. Variable z1) und den Exponenten 3 (z.B. Variable exp1), der negativ ist, positive Exponenten werden nicht betrachtet (deswegen hat der Exponent auch kein Vorzeichen)!

Der String zahl2 z.B. 23,12 wird zerlegt in 2312*10^-2, daraus bekommt man 2312 (z.B. Variable z2) und den Exponenten 2 (z.B. Variable exp2), der negativ ist, positive Exponenten werden nicht betrachetet, da sie auch hier nicht vorkommen!

Um beide Zahlen zu verrechnen (addieren, subtrahieren, muss geschaut werden, welches der Größte Exponent ist.
Hier ist dies der Exponent der Ersten Zahl, der 3 ist. jetzt muss geschaut werden, wie gross die Differenz zum Anderen Exponenten ist, der 2 ist.
Die Differen ist 1, also 10mal bzw. 10^1.
Somit muss die 2. Zahl 2312 mit 10 Multipliziert werden, um auf den gleichen Exponenten zu kommen. (wäre der Unterschied 2, dann mit 100, bei 3 mit 1000 usw.)
Aus der 2. Zahl 2312 mit dem Exponenten 2 wird 23120 mit dem Exponenten 3 (natürlich sind die Exponenten immernoch negativ, da sie die Zahl verkleinern, das Komma nach links verschieben, dies wird bei der Ausgabe erst beachtet).
jetzt kann man beide Zahlen addieren oder Subtrahieren.

Für die Addition könnte das z.B. so aussehen:

  4123
+23120
=27243

Der Exponent für beide Zahlen war 3, also müssen wir für die Ausgabe ein Komma an der 3. Stelle von rechts einfügen.
die Ausgabe wäre dann also 27,243 und wieder ein String.

Die Subtraktion wäre dann ähnlich auszuführen (alles das gleiche nur bei der Rechnung wird subtrahiert nicht addiert).

  4123
-23120
=-18997

für die Ausgabe wieder das Komma an dritter Stelle von rechts, also -18,997.

Tja, soviel zur Theorie, die soweit klappt, jetzt noch alles mit Java umsetzen...
z.B. wie kann ich das Komma in den Ausgabestring setzen?


----------



## Landei (2. Jun 2009)

Darksideone hat gesagt.:


> So, hab mir noch bissel was zum Verrechnen überlegt.
> Tja, soviel zur Theorie, die soweit klappt, jetzt noch alles mit Java umsetzen...
> z.B. wie kann ich das Komma in den Ausgabestring setzen?



Wieso, funktioniert mein Code nicht? Da hatte ich doch schon die Addition drin...


----------



## Darksideone (2. Jun 2009)

@Landei 
Hm, den teil hab ich übersehen, hanswurst  hatte dazu ja nix.
(Würde ja am liebsten sagen, der Code ist genial, aber soweit bin ich noch nicht, stehe mit Java noch auf dem Kriegspfad.)

Jetzt hat man aber die Funktionalität auch mal ausgeschrieben.


----------



## Darksideone (3. Jun 2009)

auf Java ist auch eine Insel - Programmieren für die Java 2-Plattform in der Version 1.4 findet man auch einen Codeschnipsel, der gut für die Operationsabfrage zu gebrauchen sein dürfte:

Beispiel Ein Taschenrechner mit Alternative 
switch ( op )
{
  case '+':   // addiere
    break;

  case '-':   // subtrahiere
    break;

  case '*':   // multipliziere
    break;

  case '/':   // dividiere
    break;

  default:
    System.err.println( "Operand nicht definiert!" );
}


----------



## hanswurst (3. Jun 2009)

@Landei : Könnte man von deinem Zahl-Konstrukt auch rigendwie ein Array basteln und das dann weiter verwenden?

also zum Beispiel, dass ich aus mit deiner Zahl sowas mache:

```
Zahl[] z = new Zahl[ 2 ];
    z[0] = new Zahl(2,3);
```
wenn ich nen Array der Länge 2 davon haben wollte und z[0] soll eine Zahl mit basis 2 und exponent 3 sein... oder ergibt das überhaupt keinen Sinn?

allerdings meckert da auch Netbeans bei mir .... (ahso funktioniert sogar, musste das nur in ne Methode reinpacken.)

dachte mir so könnte man irgendwie mit den vorgegebenen Methodenköpfen arbeiten.

Danke 

hanswurst


----------



## Landei (3. Jun 2009)

Das würde so gehen, aber die Methodenköpfe ergeben für mich keinen Sinn: Bei der Methode eingabe wird z.B. ein Zahl[] zurückgeliefert, obwohl nur eine Zahl eingelesen wird. Das Addieren von einem Array von Zahlen würde ich ja noch angehen lassen, aber _Subtrahieren_? Irgendwie stimmt das alles vorn und hinten nicht.
Man könnte (aus didaktischen Gründen, *niemals* im wirklich Leben) ein Zahl auch durch ein int[] mit zwei Elementen (z[0] als Basis und z[1] als Exponent) darstellen, aber selbst dann hauen die Methoden-Signaturen nicht hin, weil ja kein Array, sondern nur wieder eine "Zahl" zurückgeliefert wird - und außerdem war ja von einem _neuen_ Datentyp die Rede, und das wäre int[] nun wirklich nicht.

Hast du keine Möglichkeit, nochmal nachzufragen? Das sieht für mich mächtig nach einem Irrtum in der Aufgabenstellung aus.


----------



## hanswurst (4. Jun 2009)

wird nachgetragen...


----------



## hanswurst (5. Jun 2009)

habs jetzt so zum laufen gebracht:


```
import java.io.*;
import java.util.regex.*;

/**
 *  Bereitstellung einer Zahl in Exponentialdarstellung mit zusätzlichen Methoden zum verrechnen solcher Zahlen.
 * @author hanswurst
 * @version 0.1
 */
public class GKZahl {

    //
    // Felder
    //
    int basis;
    int exponent;
    static GKZahl[] z = new GKZahl[2];
    static GKZahl erg = new GKZahl();

    //
    // Konstruktoren
    //
    // defaultkonstruktor
    /**
     * Setzt Basis und Exponent = 0
     */
    public GKZahl() {
        basis = 0;
        exponent = 0;
    }

    // Ereugung einer GleitkommaZahl mit basis und exponent.
    /**
     * Basis und Exponent können einzeln übergeben werden.
     * @param basis Objekt vom Typ Int
     * @param exponent Objekt vom Typ Int
     */
    public GKZahl(int basis, int exponent) {
        this.basis = basis;
        this.exponent = exponent;
    }

    //
    // Methoden
    //
    // Einlesen
    /**
     * Liest 2 Gleitkommazahlen ein und speichert diese in einem Array vom Typ GKZahl
     * @return GKZahl[] Array vom Typ GKZahl
     */
    public GKZahl[] einlesen() throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String s;
        for (int i = 0; i <= 1; i++) {
            System.out.println("Bitte geben Sie eine Zahl ein:");
            s = br.readLine();
            // Nur Zahlen der Form "Zahl1,Zahl2" sind erlaubt, Zahl2 ist nicht zwingend erforderlich
            Pattern p = Pattern.compile("[0-9]+,?[0-9]*");
            Matcher m = p.matcher(s);
            if (m.matches() == false) {
                throw new IllegalArgumentException("Keine gueltige Eingabe! (Bsp für Eingabe : 1,25)");
            }
            // Exponent sind die Nachkommastellen : Länge des Strings -1 -index vom Komma
            int komma = s.indexOf(',');
            if (komma == -1) {
                z[i] = new GKZahl(Integer.parseInt(s), 0);
            } else {
                z[i] = new GKZahl(Integer.parseInt(s.substring(0, komma) + s.substring(komma + 1)), s.length() - 1 - komma);
            }
        }
        return z;
    }

    // Addieren
    /**
     * addiert die in dem Array gespeicherten Gleitkommazahlen
     * @param Add Array vom Typ GKZahl
     * @return GKZahl Ojekt vom Typ GKZahl
     */
    GKZahl addieren(GKZahl Add[]) {
        erg.exponent = Math.max(Add[0].exponent, Add[1].exponent);
        for (int i = 0; i <= 1; i++) {
            while (Add[i].exponent < erg.exponent) {
                Add[i].exponent++;
                Add[i].basis *= 10;
            }
        }
        erg.basis = Add[0].basis + Add[1].basis;
        return erg;
    }

    // Subtrahieren
    /**
     * subtrahiert die in dem Array gespeicherten Gleitkommazahlen
     * @return Objekt vom Typ GKZahl
     * @param Array vom Typ GKZahl
     */
    GKZahl subtrahieren(GKZahl Add[]) {
        erg.exponent = Math.max(Add[0].exponent, Add[1].exponent);
        for (int i = 0; i <= 1; i++) {
            while (Add[i].exponent < erg.exponent) {
                Add[i].exponent++;
                Add[i].basis *= 10;
            }
        }
        erg.basis = Add[0].basis - Add[1].basis;
        return erg;
    }

    // Ausgabe
    /**
     * Gibt das Ergebnis aus
     * @param Objekt vom Typ GKZahl
     */
    void ausgabe(GKZahl erg) {
        String tmp1 = Integer.toString(erg.basis);
        String tmp2 = Double.toString(erg.basis * Math.pow(10, -erg.exponent));
        System.out.println("Ergebnis : " + tmp2.substring(0, tmp1.length() + 1));
    }
}
```
und dann noch zusätzlich ne Taschenrechner.java die die Klasse GKZahl nutzt

```
import java.io.*;

/**
 * Klasse Taschenrechner nutzt die Klasse GKZahl zum addieren bzw. subtrahieren zweier Zahlen.
 * @author hanswurst
 * @version 0.1
 */
public class Taschenrechner {

    public static void main(String[] args) throws IOException {
        GKZahl rechner = new GKZahl();
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        rechner.einlesen();
        System.out.println("+ fuer Addition, - fuer Subtraktion");
        char s = br.readLine().charAt(0);
        switch (s) {
            case '+':
                rechner.addieren(GKZahl.z);
                rechner.ausgabe(GKZahl.erg);
                break;
            case '-':
                rechner.subtrahieren(GKZahl.z);
                rechner.ausgabe(GKZahl.erg);
                break;
            default:
                System.err.println("Unknown operator " + s);
        }
    }
}
```

Allerdings habe ich manchmal das Problem, dass total wirre Ergebnisse rauskommen. Denke das passiert wen man Zahlen mit vielen Ziffern nimmt und das wenn die im Ergebnis zusammenaddiert werden irgendwie da was zum Überlauf kommt. oder müsste es dann ne Exception oder sowas geben?

Naja ist eigtl auch erstmal egal.

Gruß,
hanswurst


----------



## Darksideone (7. Jun 2009)

bei Pattern p = Pattern.compile("[0-9]+,?[0-9]*"); würde ich aber noch mindestens - mit dazu nehmen, oder muss man keine negativen Zahlen eingeben können?

Wie sieht es denn mit der Ausgabe aus? Eingabe mit , aber Ausgabe mit .? ist das nur ein Fehler, oder soll da wirklich die Ausgabe mit einem Punkt erfolgen?

falls nicht, kann man z.B. mit strg.insert(<wievielteStellevonlinks>,',');
z.B. strg.insert(2,'.');
würde z.B. aus dem String strg mit Inhalt 1234 12,34 machen....


----------

