Taschenrechner Punkt vor Strich

  • Themenstarter Themenstarter JavaLehrling
  • Beginndatum Beginndatum
J

JavaLehrling

Gast
Hallo,

es geht um folgendes. Ich habe einen Taschenrechner implementiert . Beim Aufruf des Taschenrechners übergebe ich die Werte (z.b 5 * 5 + 10)...Leider kennt mein Taschenrechner die Vorrangregeln nocht nicht (Punkt vor Strich) außerdem komme ich nicht mehr aus der Schleife raus, sobald ich einmal drinnen bin. Kann mir jemand mit den beiden Problemen weiterhelfen?

Java:
import java.util.Scanner;
import java.util.Stack;

public class Calculator {
	
	public static void main(String[] args){
		
		Scanner scan = new Scanner(System.in);
		Scanner scan2 = new Scanner(System.in);
		
		int sum = 0;
		int i = scan.nextInt();
		
				
		while (scan.hasNext() == true) {
			String op = scan.next();
			int j = scan.nextInt();
			
			if (op.equals("*")){
				if (sum == 0)
					sum = i*j;
				else sum = sum*j;
			}
			
			else if (op.equals("/")){
				if(sum == 0)
					sum = i/j;
				else sum = sum/j;
			}
			
			else if (op.equals("+")){
				if (sum == 0)
					sum = i + j;
				else sum = sum +j;
			}
			
			else if (op.equals("-")){
				if(sum == 0)
					sum = i-j;
				else sum = sum -j;
			}
		
		System.out.println(sum);
		
		}
			
	}
}
 
das zum Abbruch habe ich doch schon geschrieben, nicht einfach so nochmal fragen
http://www.java-forum.org/java-basics-anfaenger-themen/134681-calculator-java.html

wenn du beim Eintippen von 5 - 4 schon 1 errechnest und 5 und 4 wegwirfst,
dann kann natürlich bei insgesamt 5 - 4 * 3 später nicht mehr 4 * 3 gerechnet werden, denn die 4 ist schon weg

das zu lösen ist kein 2 Min.-Posting im Forum sondern ein stundenlanger Umbau bzw. Bau eines richtigen Programms statt bisheriger Fingerübung,
macht deinen Calculator zigmal komplizierter als bisher,
sehr fraglich ob du das selber hinbekommen kannst,
im Internet gibt es fertige Programme, aber ob du die dann verstehst?
 
Achso, dachte ich kann das vielleicht mit nem if-Befehl lösen, dass die "/" und "*" zuerst gelöst werden 😀... also wird das mal nichts. Ok dann belass ichs vorerst bei dem Programm... Danke für die Hilfe
 
Ne "if-Befehle" reichen da nicht. Brauchst da schon bisschen mehr.
Ein für dich einfacherer Ansatz könnte der folgende sein (einfach
so mal aus der Luft gegriffen):

- Du speicherst deinen Term in einem String.
- Den String durchläufst du und prüfst die Rechenzeichen
- Solange "/" oder "*" darin vorkommt
- Suche Zahl da vor und da hinter
- Berechne "Zahl Rechenzeichen Zahl"
- .....
 
Ich hab auch so einen Taschenrechner geschrieben. Die Methode zum parsen eines Strings ist im Moment 160 Zeilen lang, war aber zwischenzeitlich auch mal länger. Die Hauptmethode arbeitet bei mir Rekursiv und der ganze Parsing-Algorithmus beruht auf der Idee von irgendeinem Post hier zu einem ähnlichen Thema (muss schon ein Jahr her sein). Meine Methode arbeitet mit einer schon fertig gesplitteten Liste und ersetzt die schon geparsten Teile in dieser dann durch Objekte. Daneben hab ich noch ein ganzes Set von Klassen, die die Einzelnen Rechenoperationen wiedergeben, das liegt allerdings daran, dass diese Klassen mehr können als nur den Wert eines geparsten Terms auszurechnen, sondern ihn auch bildlich darstellen und kürzen. Auserdem enthält mein Programm auch Variablen, sodass ein einmal geparster Term wie eine Funktion benutzt werden kann und mit einmal parsen beliebig lange Wertereihe liefert. Das ganze lässt sich natürlich unendlich weiterprogrammieren, geplant ist Mal ohne Zeichen, z.B. 2x oder 2pi, und das aussrechnen von Nullstellen und Ableitungen, aber wenn ich noch viel mehr ergänze kann ich auch gleich bei GeoGebra mitmachen.

Mein Algorithmus mal in Kürze:
1. Den übergebenen String in einzele Tokens splitten
2. Die Liste zu einem Termobjekt parsen:
a) Wenn die Liste nur noch ein Objekt enthält, dieses parsen und zurückgeben, dies muss entweder eine Zahl/Variable sein, oder ein schon geparstes Termobjekt
b) Klammern durch geparste Termobjekte ersetzen, nach jeder Ersetzung wird wieder bei 2. Angefangen
c) Vorzeichen(+-!~) durch Termobjekte ersetzen -> 2.
d) Jetzt werden die normalen Rechenzeichen geparst, angefangen mit denen der niedrigsten Priorität. (Bei mir läuft das in einer Schleife, aber das macht bei zwei Prioritäten noch keine Sinn, deswegen war die Methode zu Anfang länger) Die Liste wird dabei von hinten(!) nach vorne durchsucht (sonst würde z.B. 5-1-1= 5-(1-1) geparst werden und damit 5) und und wenn ein passendes Rechenzeichen gefunden wird, wird die Liste an diesem Punkt in zwei Teile gesplittet und diese geparst und dann das geparste Ergebnis zurückgegeben.

Ich hoffe das ist verständlich.
 
OK, jetzt sollte es so ziemlich passen ... Sobald ich es nun teste stimmt das meiste. z.b 3 + 3 * 3 = 12. oder 5 + 5 / 5 = 6.
Aber manches funktioniert noch nicht z.b: 8 - 2 * 3.

Seht ihr den Fehler??

Danke bereits im Vorhinen

Code:

Java:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;
import java.util.Stack;
import java.io.*;

public class RechnerErweitert {
	
	public static void main(String[] args) throws IOException{	
		InputStreamReader inStream = new InputStreamReader(System.in);
		BufferedReader stdin = new BufferedReader(inStream);
		
		String eing = null;
		int sum = 0;
		
		System.out.println("Eingabe");
		eing = stdin.readLine();
		int length = eing.length();
		
		char[] array = new char[10];
		array = eing.toCharArray();
			
		Scanner scan = new Scanner(eing);
		int i = scan.nextInt();
		
		
		for(int l=0;l<length;l=l+5){
			
			String op = scan.next();
			int j = scan.nextInt();
			
			if (op.equals("*")){
				if (sum == 0)
					sum = i*j;
				else sum = sum*j;
			}
			
			else if (op.equals("/")){
				if(sum == 0)
					sum = i/j;
				else sum = sum/j;
			}			
		}
//-------------------------------------------------------------------------
		Scanner scan2 = new Scanner(eing);
		int a = scan2.nextInt();
		
		for(int l=0;l<length;l=l+5){
			
			String op = scan2.next();
			int b = scan2.nextInt();
			
			if (op.equals("+")){
				if (sum == 0)
					sum = a + b;
				else sum = sum + b;
			}
			
			else if (op.equals("-")){
				if(sum == 0)
					sum = a - b;
				else sum = sum - b;
			}		
		}
		
		System.out.println(sum);
			
	}
}
 
dein Programm besteht aus einer Codezeile nach der anderne, das kann man doch alles prüfen,
wenn nicht im Kopf, dann mit System.out.println(), verfolge was jeder Schleifendurchlauf macht, welche Variablen wann was macht usw..

mit gleichen Zahlen funktioniert manches, aber nur zufällig,
besser sieht man es an verschiedenen Zahlen wie eben
8 - 2 * 3

i ist 8,
erste Schleife kommt dran,
bei - 2 passiert gar nix,
aber dann * 3, i ist immer noch 8, 8*3 wird zu 24 gerechnet
und so geht es immer weiter, schauen und verstehen was das Programm macht

an eine Lösung will ich noch nicht direkt denken, bin immer noch skeptisch dass das mit einfachen Schleifen und ifs machbar ist,
ok, letzlich bestehen alle Programme aus diesen Mitteln, aber geht auch etwas aufwendiger
 
Ich habe das Parsen einer Formel bzw. eines Rechenausdrucks immer für eine relativ komplizierte Sache gehalten bis ich auf folgendes gestossen bin:

Die Umgekehrte Polnische Notation

Gelegentlich wird sie auch als Postfix-Notation bezeichnet. Der Operator (Rechenzeichen)
steht nach den Operanden (Post = danach).

Also 5 + 4 wird dann zu 5 4 +

Unsere gebräuchliche Notation ist eine Infix-Notation (der Operator steht zwischen den Zahlen)

Ein UPN-Ausdruck wird immer von links nach rechts gelesen. Das erste Rechenzeichen wird genommen und mit den beiden Zahlen davor das Ergebnis berechnet. Die beiden Zahlen und das Rechenzeichen
werden durch das Ergebnis ersetzt:

5 4 * 3 + würde wie folgt berechnet:

Start
5 4 * 3 +​
1.Schritt
20 3 +​
2.Schritt
23​

Im Wikipedia-Artikel findest Du weiteres. Dort wird auch auf einen Artikel in englischer Sprache verwiesen, der erklärt, wie aus einer Infix-Notation (unsere Schreibweise) eine Postfixnotation macht.

Ich würde das Problem in 2 Schritten lösen:

  1. 1 Umformen des Ausdrucks in die Umgekehrte Polnische Notation (UPN)
  2. 2 Auswerten des Ausdrucks in UPN

Beides ist in dem englischsprachigen Artikel beschrieben. Das muss man sich erst durcharbeiten.
Aber es lohnt sich.
 

Zurück
Oben