Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 78 additions & 28 deletions app/src/main/java/htw/berlin/prog2/ha1/Calculator.java
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -14,6 +16,9 @@ public class Calculator {

private String latestOperation = "";

private ArrayList<Double> saveLastValues = new ArrayList<>();
private ArrayList<String> saveLastOperation = new ArrayList<>();

/**
* @return den aktuellen Bildschirminhalt als String
*/
Expand All @@ -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() {
Expand All @@ -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";
}

/**
Expand All @@ -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);

}

/**
Expand Down Expand Up @@ -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<Double> zwischenWert = new ArrayList<>();
List<String> 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;
}
}
}
79 changes: 79 additions & 0 deletions app/src/test/java/htw/berlin/prog2/ha1/CalculatorTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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);
}

}