diff --git a/app/src/main/java/htw/berlin/prog2/ha1/Calculator.java b/app/src/main/java/htw/berlin/prog2/ha1/Calculator.java index 84c04f21..e133725e 100644 --- a/app/src/main/java/htw/berlin/prog2/ha1/Calculator.java +++ b/app/src/main/java/htw/berlin/prog2/ha1/Calculator.java @@ -1,4 +1,6 @@ package htw.berlin.prog2.ha1; +import java.util.ArrayList; +import java.util.List; /** * Eine Klasse, die das Verhalten des Online Taschenrechners imitiert, welcher auf @@ -14,6 +16,9 @@ public class Calculator { private String latestOperation = ""; + private ArrayList saveLastValues = new ArrayList<>(); + private ArrayList saveLastOperation = new ArrayList<>(); + /** * @return den aktuellen Bildschirminhalt als String */ @@ -23,25 +28,23 @@ public String readScreen() { /** * Empfängt den Wert einer gedrückten Zifferntaste. Da man nur eine Taste auf einmal - * drücken kann muss der Wert positiv und einstellig sein und zwischen 0 und 9 liegen. + * drücken kann, muss der Wert positiv und einstellig sein und zwischen 0 und 9 liegen. * Führt in jedem Fall dazu, dass die gerade gedrückte Ziffer auf dem Bildschirm angezeigt * oder rechts an die zuvor gedrückte Ziffer angehängt angezeigt wird. * @param digit Die Ziffer, deren Taste gedrückt wurde */ public void pressDigitKey(int digit) { if(digit > 9 || digit < 0) throw new IllegalArgumentException(); - - if(screen.equals("0") || latestValue == Double.parseDouble(screen)) screen = ""; - + if(screen.equals("0") || Double.parseDouble(screen) == 0) screen = ""; screen = screen + digit; } /** * Empfängt den Befehl der C- bzw. CE-Taste (Clear bzw. Clear Entry). - * Einmaliges Drücken der Taste löscht die zuvor eingegebenen Ziffern auf dem Bildschirm - * so dass "0" angezeigt wird, jedoch ohne zuvor zwischengespeicherte Werte zu löschen. + * Einmaliges Drücken der Taste löscht die zuvor eingegebenen Ziffern auf dem Bildschirm, + * sodass "0" angezeigt wird, jedoch ohne zuvor zwischengespeicherte Werte zu löschen. * Wird daraufhin noch einmal die Taste gedrückt, dann werden auch zwischengespeicherte - * Werte sowie der aktuelle Operationsmodus zurückgesetzt, so dass der Rechner wieder + * Werte sowie der aktuelle Operationsmodus zurückgesetzt, sodass der Rechner wieder * im Ursprungszustand ist. */ public void pressClearKey() { @@ -52,16 +55,17 @@ public void pressClearKey() { /** * Empfängt den Wert einer gedrückten binären Operationstaste, also eine der vier Operationen - * Addition, Substraktion, Division, oder Multiplikation, welche zwei Operanden benötigen. + * Addition, Subtraktion, Division, oder Multiplikation, welche zwei Operanden benötigen. * Beim ersten Drücken der Taste wird der Bildschirminhalt nicht verändert, sondern nur der * Rechner in den passenden Operationsmodus versetzt. * Beim zweiten Drücken nach Eingabe einer weiteren Zahl wird direkt des aktuelle Zwischenergebnis * auf dem Bildschirm angezeigt. Falls hierbei eine Division durch Null auftritt, wird "Error" angezeigt. - * @param operation "+" für Addition, "-" für Substraktion, "x" für Multiplikation, "/" für Division + * @param operation "+" für Addition, "-" für Subtraktion, "x" für Multiplikation, "/" für Division */ public void pressBinaryOperationKey(String operation) { - latestValue = Double.parseDouble(screen); - latestOperation = operation; + saveLastValues.add(Double.parseDouble(screen)); + saveLastOperation.add(operation); + screen = "0"; } /** @@ -74,16 +78,16 @@ public void pressBinaryOperationKey(String operation) { public void pressUnaryOperationKey(String operation) { latestValue = Double.parseDouble(screen); latestOperation = operation; - var result = switch(operation) { - case "√" -> Math.sqrt(Double.parseDouble(screen)); - case "%" -> Double.parseDouble(screen) / 100; - case "1/x" -> 1 / Double.parseDouble(screen); + double result = 0.0; + switch(operation) { + case "√" -> result = Math.sqrt(Double.parseDouble(screen)); + case "%" -> result = Double.parseDouble(screen) / 100; + case "1/x" -> result = 1 / Double.parseDouble(screen); default -> throw new IllegalArgumentException(); }; screen = Double.toString(result); if(screen.equals("NaN")) screen = "Error"; if(screen.contains(".") && screen.length() > 11) screen = screen.substring(0, 10); - } /** @@ -117,17 +121,63 @@ public void pressNegativeKey() { * Operation (ggf. inklusive letztem Operand) erneut auf den aktuellen Bildschirminhalt angewandt * und das Ergebnis direkt angezeigt. */ + public void pressEqualsKey() { - var result = switch(latestOperation) { - case "+" -> latestValue + Double.parseDouble(screen); - case "-" -> latestValue - Double.parseDouble(screen); - case "x" -> latestValue * Double.parseDouble(screen); - case "/" -> latestValue / Double.parseDouble(screen); - default -> throw new IllegalArgumentException(); - }; - screen = Double.toString(result); - if(screen.equals("Infinity")) screen = "Error"; - if(screen.endsWith(".0")) screen = screen.substring(0,screen.length()-2); - if(screen.contains(".") && screen.length() > 11) screen = screen.substring(0, 10); + saveLastValues.add(Double.parseDouble(screen)); + double result; + try { + result = checkOperation(); + if (result % 1 == 0) { + screen = Integer.toString((int) result); + } else { + screen = Double.toString(result); + } + //if (screen.equals("Infinity") || screen.equals("NaN")) {screen = "Error";} + }catch (ArithmeticException e) { + screen = "Error"; + } + } + + + public double checkOperation() { //2 Durchgänge - 1. Erledigt alle "Punkt"(multiplikation/division) Aufgaben + List zwischenWert = new ArrayList<>(); + List restOperationen = new ArrayList<>(); + + double aktWert = saveLastValues.get(0); + for (int i = 0; i < saveLastOperation.size(); i++) { + String operation = saveLastOperation.get(i); + double nextWert = saveLastValues.get(i + 1); + + switch (operation) { + case "x": + aktWert *= nextWert; + break; + case "/": + if (nextWert == 0) { + throw new ArithmeticException("Division durch null!"); + }else{aktWert /= nextWert;} + break; + default: + zwischenWert.add(aktWert); + restOperationen.add(operation); + aktWert = nextWert; + break; + } + } + zwischenWert.add(aktWert); + + double result = zwischenWert.get(0); // 2. Durchgang - Erledigt alle "Strich"(Addition/Subtraktion) Aufgaben + for (int i = 0; i < restOperationen.size(); i++) { + String operation = restOperationen.get(i); + double nextWert = zwischenWert.get(i + 1); + if (operation.equals("+")) { + result += nextWert; + } else if (operation.equals("-")) { + result -= nextWert; + } else { + throw new IllegalArgumentException("Falsche Operation"); + } + } + return result; } -} +} \ No newline at end of file diff --git a/app/src/test/java/htw/berlin/prog2/ha1/CalculatorTest.java b/app/src/test/java/htw/berlin/prog2/ha1/CalculatorTest.java index ddff0daf..1a0fe5e2 100644 --- a/app/src/test/java/htw/berlin/prog2/ha1/CalculatorTest.java +++ b/app/src/test/java/htw/berlin/prog2/ha1/CalculatorTest.java @@ -24,6 +24,9 @@ void testPositiveAddition() { String actual = calc.readScreen(); assertEquals(expected, actual); + System.out.println("testPositiveAddition()"); + System.out.println("Ausgerechnetes Ergebnis: " + actual); + System.out.println("Erwartetes Ergebnis: " + expected); } @Test @@ -38,6 +41,9 @@ void testSquareRoot() { String actual = calc.readScreen(); assertEquals(expected, actual); + System.out.println("testSquareRoot()"); + System.out.println("Ausgerechnetes Ergebnis: " + actual); + System.out.println("Erwartetes Ergebnis: " + expected); } @Test @@ -54,6 +60,9 @@ void testDivisionByZero() { String actual = calc.readScreen(); assertEquals(expected, actual); + System.out.println("testDivisionByZero"); + System.out.println("Ausgerechnetes Ergebnis: " + actual); + System.out.println("Erwartetes Ergebnis: " + expected); } @Test @@ -69,6 +78,9 @@ void testSquareRootOfNegative() { String actual = calc.readScreen(); assertEquals(expected, actual); + System.out.println("testSquareRootOfNegative()"); + System.out.println("Ausgerechnetes Ergebnis: " + actual); + System.out.println("Erwartetes Ergebnis: " + expected); } @Test @@ -86,9 +98,76 @@ void testMultipleDecimalDots() { String actual = calc.readScreen(); assertEquals(expected, actual); + System.out.println("testMultipleDecimalDots"); + System.out.println("Ausgerechnetes Ergebnis: " + actual); + System.out.println("Erwartetes Ergebnis: " + expected); } //TODO hier weitere Tests erstellen + @Test + @DisplayName("Soll eine Zahl von einer anderen Abziehen") + void testSubtract() { + Calculator calc = new Calculator(); + + calc.pressDigitKey(2); + calc.pressBinaryOperationKey("-"); + calc.pressDigitKey(1); + calc.pressEqualsKey(); + + String expected = "1"; + String actual = calc.readScreen(); + + assertEquals(expected, actual); + System.out.println("testSubtract()"); + System.out.println("Ausgerechnetes Ergebnis: " + actual); + System.out.println("Erwartetes Ergebnis: " + expected); + } + + @Test + @DisplayName("Soll mehr als nur zwei Zahlen zusammenrechnen.") + void testSubtractAndMultiply() { + Calculator calc = new Calculator(); + + calc.pressDigitKey(2); + calc.pressBinaryOperationKey("-"); + calc.pressDigitKey(1); + calc.pressBinaryOperationKey("+"); + calc.pressDigitKey(4); + calc.pressBinaryOperationKey("+"); + calc.pressDigitKey(4); + calc.pressEqualsKey(); + + String expected = "9"; + String actual = calc.readScreen(); + assertEquals(expected, actual); + System.out.println("testSubtractAndMultiply()"); + System.out.println("Ausgerechnetes Ergebnis: " + actual); + System.out.println("Erwartetes Ergebnis: " + expected); + } + + @Test + @DisplayName("Soll punkt vor Strich ausrechnen") + void punktVorStrichTest() { + Calculator calc = new Calculator(); + + calc.pressNegativeKey(); + calc.pressDigitKey(2); + calc.pressDigitKey(0); + calc.pressBinaryOperationKey("-"); + calc.pressDigitKey(3); + calc.pressBinaryOperationKey("x"); + calc.pressDigitKey(4); + calc.pressEqualsKey(); + + String expected = "8"; + String actual = calc.readScreen(); + + assertEquals(expected, actual); + System.out.println("punktVorStrichTest()"); + System.out.println("Ausgerechnetes Ergebnis: " + actual); + System.out.println("Erwartetes Ergebnis: " + expected); + } + }