Wie programmiere ich meinen Taschenrechner effizienter? (vorerst ohne GUI)

vram78

Lieutenant
Registriert
Dez. 2015
Beiträge
717
Hi,
Ich schaffe es irgendwie nicht, dass, nachdem man "ja" eingegeben hat, die Schleife so lange weitermacht, bis man nein eingibt. Aber ansonsten habe ich es zum laufen gebracht und es funktioniert. Nur finde ich, dass es irgendwie unübersichtlich aussieht, hat da jemand Tipps für mich?

Java:
package me.programm;
import java.util.Scanner;

public class calculator {

    public static void main(String[] args) {
    
        
        Scanner input1 = new Scanner(System.in);     
        Scanner input2 = new Scanner(System.in);
        Scanner arithmeticSign = new Scanner(System.in);
        Scanner input3 = new Scanner(System.in);
        System.out.println("first number:");       
        double firstInput = input1.nextDouble();                 
        System.out.println("second number");
        double secondInput = input2.nextDouble();
        System.out.println("choose an arithmetic sign");
        String sign = arithmeticSign.next();
        System.out.print("the result is: ");
    
        
        
        if(sign.equals("+")) {
            System.out.println(addition(firstInput,secondInput));
        
        } else if(sign.equals("-")) {
            System.out.println(subtraktion(firstInput,secondInput));
            
        } else if(sign.equals("*")) {
            System.out.println(multiplikation(firstInput,secondInput));
        } else if(sign.equals("/")) {
            System.out.println(division(firstInput,secondInput));
        } else {
            System.out.println("type a valid arithmetic sign!");
        }
        
        boolean schleife = true;
        System.out.println("Neue Recheneinheit?");
        String abfrage = input3.next();
        
    if(abfrage.equals("nein")) {   
        System.out.println("Programmende");
        System.exit(0);
    } else {
        while(abfrage.equals("ja") == schleife) {
            Berechne();
            System.out.println("Neue Recheneinheit?");
            abfrage = input3.next();
            while(abfrage.equals("ja") == schleife) {
                Berechne();
            System.out.println("Neue Recheneinheit?");
            }
        }
    
    }
    }
    
    
    public static void Berechne() {
        Scanner input1 = new Scanner(System.in);     
        Scanner input2 = new Scanner(System.in);
        Scanner arithmeticSign = new Scanner(System.in);
        Scanner input3 = new Scanner(System.in);
        System.out.println("first number:");       
        double firstInput = input1.nextDouble();                 
        System.out.println("second number");
        double secondInput = input2.nextDouble();
        System.out.println("choose an arithmetic sign");
        String sign = arithmeticSign.next();
        System.out.print("the result is: ");
    
        
        
        if(sign.equals("+")) {
            System.out.println(addition(firstInput,secondInput));
        
        } else if(sign.equals("-")) {
            System.out.println(subtraktion(firstInput,secondInput));
            
        } else if(sign.equals("*")) {
            System.out.println(multiplikation(firstInput,secondInput));
        } else if(sign.equals("/")) {
            System.out.println(division(firstInput,secondInput));
        } else {
            System.out.println("type a valid arithmetic sign!");
        }
        
    }
    
    public static double addition(double a, double b) {
        double result = a+b;
        return result;
    }
    
public static double subtraktion(double a, double b) {
        double result = a-b;
        return result;
    }
public static double multiplikation(double a, double b) {
    double result = a*b;
    return result;
}
public static double division(double a, double b) {
    double result = a/b;
    return result;
}
    
    
}
Gruß
 
vll solltest du deine while schleife um den kompletten code in der main methode packen. die 2. while in der while schleife ist unnötig

so ungefähr (ungetestet):

Java:
 public static void main(String[] args) {
  
     do{
         Berechne();
        System.out.println("Neue Recheneinheit?");
        String abfrage = input3.next();
    } while(abfrage.equals("ja"));
  
    System.out.println("Programmende");
    System.exit(0);
      
    }

du solltes auch noch etwas am style arbeiten...Klassennamen Gross Methodennamen klein schreiben etc. in ner gute IDE wie intellij idea wird dir sowas gleich verbessert/angemerkt
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: BeBur, J@ck, vram78 und eine weitere Person
Im Prinzip einfach das if entfernen. Wenn du was anderes als ja eingibst, läuft es ans "Programmende".
Die while-Schleife läuft ja nur so lange du "ja" eingibst.

Und bitte bitte bitte kein denglischen Code. Variablen und Funktionen bitte auf englisch. (Außer dein (unfähiger, sorry) Professor/Lehrer fordert es).

Beste Grüße,
Dominic
 
  • Gefällt mir
Reaktionen: vram78
dominic.e schrieb:
Außer dein (unfähiger, sorry) Professor/Lehrer fordert es)
Es könnte ja auch sein das er seine Schüler eigene Erfahrungen machen lässt SCNR
 
  • Gefällt mir
Reaktionen: J@ck, dominic.e und vram78
dominic.e schrieb:
Und bitte bitte bitte kein denglischen Code. Variablen und Funktionen bitte auf englisch
Die konsistente Verwendung deutscher Bezeichner (es geht hierbei nicht nur um Variablen) ist selbstverständlich auch in Ordnung. Maßgeblich sollten die Programmierrichtlinien sein, nicht die Vorlieben einzelner Nutzer.

Zurück zum Thema: Im Moment fragst du einzeln die Operanden sowie den Operator ab. Wie wäre es, wenn sich dies in einer einzelnen Zeile abfrühstücken ließe? Vielleicht wäre das eine Richtung, in die du gehen könntest ...
 
Der Threadtitel ist ein wenig widersprüchlich. Du fragst dort danach wie du das Programm effizienter gestalten kannst, stellst in #1 aber eine konkrete Frage zu einem konkreten Problem. Selbiges sollte eigentlich mittlerweile gelöst sein bzw. mit Hilfe von @honky-tonk 's Beitrag zu lösen sein. Ist das Thema damit nun durch?

Ansonsten fiele mir für die Übersichtlichkeit zB noch switch case ein anstelle des if-else if-else-Konstrukts. Damit ließe sich beispielsweise ohne erneutes else-if oder boolsche Aneinanderkettung ein case ":": auch der : als Divisionsoperator umsetzen, einfach als fall-through-case im selben Block wo dann case "/": stünde.
Switch-case-statements sind längeren if-Ketten bei banalen Unterscheidungskriterien wie zB eine Zahl oder ein Zeichen (oder ganze Strings) in der Regel vorzuziehen, da sie eben gerade übersichtlicher sind und man nicht die Hälfte der Bedingung immer wieder neu tippen muss - wie zB das sign.equals("")
 
Na nö, effizient ist hier noch nicht viel. Das sieht man spätestens am dritten identischen Statement, was exakt dasselbe tut (Scanner x = new Scanner(System.in)).

Mathematische Terme sind hierarchisch. Entsprechend wäre ein stackbasierter Ansatz denkbar.

Außerdem ist das OO, kein Batch. In OO geht es darum, die Realität abzubilden in einem gewissen Kontext, nicht darum, irgendwas pseudomäßig nachzuplappern (das wäre prozedurale Programmierung => VB, oder halt Batch).


Wenn da schon steht VORERST ohne GUI, dann kann man gerne hergehen und den Taschenrechner buchstäblich entlang der Realität zu modellieren.

  • class Display
  • class Key
  • class NumberKey : Key
  • class OperationKey : Key
  • (andere Tasten) : Key
  • class Memory
  • (weitere Klassen)

Dann kann ich für eine konsolenbasierte Anwendung hergehen und zB static UserInput::Parse(string Input) definieren. Damit lese ich die Benutzereingabe ein und strukturiere die Eingabe in eine für den TS verständliche Form.
Wenn der Benutzer jetzt "2 * (3 + 4)" eingibt, dann muß ich das zunächst auflösen und ein Stackmodell draus bauen, zB
Code:
(*(2)(+(3)(4)))
.
Wenn ich eine GUI haben will, dann krieg ich das im Gegensatz zu einer Konsole über Tasten. Da brauch ich ein anderes Frontend.
Oder ich stelle mich hin und Portiere die "GUI-Option" auch auf die Konsole. Heißt, ich lese Zeichen für Zeichen von der Konsole - nicht den gesamten Text -- und habe "Verarbeitungsoperatoren" --- wie bei einem echten Taschenrechner, wo jede Operatortaste die Zifferneingabe abschließt und die Eingabe einer neuen Ziffer erwartet.

Meine Displayklasse kann ich dann auf die Konsole schreiben... oder ihren Wert in irgendein Control hängen, welches Teil eines UI-Elements ist.


Der Code wird dann natürlich komplexer. Aber wenn man es schlau angeht, verhält sich das Taschenrechner-Modell am PC exakt so wie der TS, den man in die Hand nehmen kann und die Dinger sind schon recht effizient.

Und richtig rechnen würde er auch noch.
 
  • Gefällt mir
Reaktionen: Raijin und vram78
l
Raijin schrieb:
Der Threadtitel ist ein wenig widersprüchlich. Du fragst dort danach wie du das Programm effizienter gestalten kannst, stellst in #1 aber eine konkrete Frage zu einem konkreten Problem.
Es sind halt 2 Fragen
Ergänzung ()

RalphS schrieb:
Und richtig rechnen würde er auch noch
Ich probier's mal, Danke
 
RalphS schrieb:
Na nö, effizient ist hier noch nicht viel.
Eben. Deswegen fragte ich ja, weil zum Thema Effizienz, das im Topic erwähnt wurde, keine konkrete Frage gestellt wurde.


RalphS schrieb:
Mathematische Terme sind hierarchisch. Entsprechend wäre ein stackbasierter Ansatz denkbar.
Da bin ich voll bei dir. Ein Taschenrechner ist eine weit verbreitete Aufgabe beim Einstieg in die Programmierung, hat vermutlich jeder von uns schon mal gemacht, sei es privat, in der Schule oder in der Ausbildung/Studium. Ich hab ihn seinerzeit mit einer rekursiven Funktion realisiert, die einfach so lange in Klammern und */ Rechnung runtergeklettert ist, bis sie sich danach Stück für Stück wieder aufgeribbelt hat und das Ergebnis lieferte. Das ganze bestand nur aus einigen wenigen Zeilen, n bischen String zerhacken und die Rekursion anfüttern ;)

Im Nachhinein wäre die Umsetzung mit polnischer Notation besser gewesen, aber ich war jung und konnte kein Polnisch ... :lol:
 
  • Gefällt mir
Reaktionen: RalphS und Backfisch
Es geht also um einen Taschenrechner auf der Kommandozeile.
Als allererstes einen Text ausgeben mit Kurzbedienungsanleitung und Kommandos. Direkt danach die Hauptschleife.
Darin die Eingabe in eine Variable lesen.
Die Eingabe in ein Switch und im Case die Logik für die Eingabe.
 
Ja genau, es geht um das Auseinandersetzen mit dem Ansatz (prozedural/funktional/OO/whatever) und den Möglichkeiten, die einem die Programmier/Scriptsprache liefert. Das eigentliche "Problem" ist nebensächlich, deswegen kann man sich auf eine möglichst vollständige Implementierung konzentrieren.

Ein TS ist nichts anderes als ein Hallo Welt "in richtig". System.out.println("hallo welt") funktioniert, aber auf OO kann ich nicht schließen, egal wie ich es mir drehe.

Inzwischen gilt das auch für Websiteprogrammierung. Da ist die Luft auch raus. (Nebenbei: da HTML ebenfalls hierarchisch ist, kann man auch da einen Stack ins Backend hängen.)


Ganz viel früher hab ich nen Taschenrechner als State Machine implementiert. Jaja, bin alt. 🤷‍♀️ Nicht sicher, ob man mit statemachines noch was anfangen kann heutzutage.... aber es war für mich Dreikäsehoch ein wahnsinnig interessanter Ansatz, immer nur den Übergang von Zuständen zu programmieren.

Auch das paßt für Taschenrechner recht gut. Man hat ja nur eine sehr begrenzte Ein- und Ausgabemöglichkeit. Aber der Code wird vergleichsweise unverständlich.
 
RalphS schrieb:
Nicht sicher, ob man mit statemachines noch was anfangen kann heutzutage....

Damit kann man auch heute noch sehr robuste System umsetzen, ist halt leider nicht so fancy ;-) .. funktioniert halt einfach ohne Leuchteffekte und so ...

So ein Taschenrechner ist eigentlich auch eine gute Übung, um sich mal mit dem Funktionsprinzip eines Stacks auseinander zu setzen. Das macht am auch das Arbeiten mit Klammern ein wenig einfacher und verhindert das man in Schleifen und If-Else Blöcken versinkt.
 
RalphS schrieb:
Nicht sicher, ob man mit statemachines noch was anfangen kann heutzutage.... aber es war für mich Dreikäsehoch ein wahnsinnig interessanter Ansatz, immer nur den Übergang von Zuständen zu programmieren.
Eine State machine, auf Deutsch Zustandsautomat, ist das Modell in der theoretischen Informatik im Bereich Formale Sprachen und Berechenbarkeit. Es ist damit Modell der praktischen Umsetzungen von Rechnern ohne dass reale Rechner jemals das Modell vollständig umsetzen werden.
Solange diese Beziehung gilt, wird es nicht aus der Mode kommen.
 
Zurück
Oben