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
304 changes: 171 additions & 133 deletions app/src/main/java/htw/berlin/prog2/ha1/Calculator.java
Original file line number Diff line number Diff line change
@@ -1,133 +1,171 @@
package htw.berlin.prog2.ha1;

/**
* Eine Klasse, die das Verhalten des Online Taschenrechners imitiert, welcher auf
* https://www.online-calculator.com/ aufgerufen werden kann (ohne die Memory-Funktionen)
* und dessen Bildschirm bis zu zehn Ziffern plus einem Dezimaltrennzeichen darstellen kann.
* Enthält mit Absicht noch diverse Bugs oder unvollständige Funktionen.
*/
public class Calculator {

private String screen = "0";

private double latestValue;

private String latestOperation = "";

/**
* @return den aktuellen Bildschirminhalt als String
*/
public String readScreen() {
return screen;
}

/**
* 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.
* 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 = "";

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.
* Wird daraufhin noch einmal die Taste gedrückt, dann werden auch zwischengespeicherte
* Werte sowie der aktuelle Operationsmodus zurückgesetzt, so dass der Rechner wieder
* im Ursprungszustand ist.
*/
public void pressClearKey() {
screen = "0";
latestOperation = "";
latestValue = 0.0;
}

/**
* 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.
* 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
*/
public void pressBinaryOperationKey(String operation) {
latestValue = Double.parseDouble(screen);
latestOperation = operation;
}

/**
* Empfängt den Wert einer gedrückten unären Operationstaste, also eine der drei Operationen
* Quadratwurzel, Prozent, Inversion, welche nur einen Operanden benötigen.
* Beim Drücken der Taste wird direkt die Operation auf den aktuellen Zahlenwert angewendet und
* der Bildschirminhalt mit dem Ergebnis aktualisiert.
* @param operation "√" für Quadratwurzel, "%" für Prozent, "1/x" für Inversion
*/
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);
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);

}

/**
* Empfängt den Befehl der gedrückten Dezimaltrennzeichentaste, im Englischen üblicherweise "."
* Fügt beim ersten Mal Drücken dem aktuellen Bildschirminhalt das Trennzeichen auf der rechten
* Seite hinzu und aktualisiert den Bildschirm. Daraufhin eingegebene Zahlen werden rechts vom
* Trennzeichen angegeben und daher als Dezimalziffern interpretiert.
* Beim zweimaligem Drücken, oder wenn bereits ein Trennzeichen angezeigt wird, passiert nichts.
*/
public void pressDotKey() {
if(!screen.contains(".")) screen = screen + ".";
}

/**
* Empfängt den Befehl der gedrückten Vorzeichenumkehrstaste ("+/-").
* Zeigt der Bildschirm einen positiven Wert an, so wird ein "-" links angehängt, der Bildschirm
* aktualisiert und die Inhalt fortan als negativ interpretiert.
* Zeigt der Bildschirm bereits einen negativen Wert mit führendem Minus an, dann wird dieses
* entfernt und der Inhalt fortan als positiv interpretiert.
*/
public void pressNegativeKey() {
screen = screen.startsWith("-") ? screen.substring(1) : "-" + screen;
}

/**
* Empfängt den Befehl der gedrückten "="-Taste.
* Wurde zuvor keine Operationstaste gedrückt, passiert nichts.
* Wurde zuvor eine binäre Operationstaste gedrückt und zwei Operanden eingegeben, wird das
* Ergebnis der Operation angezeigt. Falls hierbei eine Division durch Null auftritt, wird "Error" angezeigt.
* Wird die Taste weitere Male gedrückt (ohne andere Tasten dazwischen), so wird die letzte
* 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);
}
}
package htw.berlin.prog2.ha1;

/**
* Eine Klasse, die das Verhalten des Online Taschenrechners imitiert, welcher auf
* https://www.online-calculator.com/ aufgerufen werden kann (ohne die Memory-Funktionen)
* und dessen Bildschirm bis zu zehn Ziffern plus einem Dezimaltrennzeichen darstellen kann.
* Enthält mit Absicht noch diverse Bugs oder unvollständige Funktionen.
*/
public class Calculator {

private String screen = "0";

private double latestValue;

private String latestOperation = "";

/**
* @return den aktuellen Bildschirminhalt als String
*/
public String readScreen() {
return screen;
}

/**
* 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.
* 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 = "";

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.
* Wird daraufhin noch einmal die Taste gedrückt, dann werden auch zwischengespeicherte
* Werte sowie der aktuelle Operationsmodus zurückgesetzt, so dass der Rechner wieder
* im Ursprungszustand ist.
*/
public void pressClearKey() {
screen = "0";
latestOperation = "";
latestValue = 0.0;
}

/**
* 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.
* 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
*/
public void pressBinaryOperationKey(String operation) {
latestValue = Double.parseDouble(screen);
latestOperation = operation;
}

/**
* Empfängt den Wert einer gedrückten unären Operationstaste, also eine der drei Operationen
* Quadratwurzel, Prozent, Inversion, welche nur einen Operanden benötigen.
* Beim Drücken der Taste wird direkt die Operation auf den aktuellen Zahlenwert angewendet und
* der Bildschirminhalt mit dem Ergebnis aktualisiert.
* @param operation "√" für Quadratwurzel, "%" für Prozent, "1/x" für Inversion
*/
public void pressUnaryOperationKey(String operation) {
// Überprüfung: Bildschirmwertes null bevor ausgeführt (operation) wird
if (operation.equals("1/x") && screen.equals("0")) {
screen = "Error"; // Fehler bei Division durch null
return; // Methode verlassen
}

// Übernehmen des aktuellen Wertes und der Ausführung
latestValue = Double.parseDouble(screen);
latestOperation = operation;

// die Durchführung der berechnungen
double result = switch (operation) {
case "√" -> Math.sqrt(latestValue);
case "%" -> latestValue / 100;
case "1/x" -> 1 / latestValue;
default -> throw new IllegalArgumentException("Ungültige Operation");
};

// Ergebnisses auf den Bildschirm setzen
screen = Double.toString(result);
if (screen.equals("NaN") || screen.equals("Infinity")) {
screen = "Error";
}
if (screen.contains(".") && screen.length() > 11) {
screen = screen.substring(0, 10); // Begrenzung auf 10 Zeichen
}
}


/**
* Empfängt den Befehl der gedrückten Dezimaltrennzeichentaste, im Englischen üblicherweise "."
* Fügt beim ersten Mal Drücken dem aktuellen Bildschirminhalt das Trennzeichen auf der rechten
* Seite hinzu und aktualisiert den Bildschirm. Daraufhin eingegebene Zahlen werden rechts vom
* Trennzeichen angegeben und daher als Dezimalziffern interpretiert.
* Beim zweimaligem Drücken, oder wenn bereits ein Trennzeichen angezeigt wird, passiert nichts.
*/
public void pressDotKey() {
if(!screen.contains(".")) screen = screen + ".";
}

/**
* Empfängt den Befehl der gedrückten Vorzeichenumkehrstaste ("+/-").
* Zeigt der Bildschirm einen positiven Wert an, so wird ein "-" links angehängt, der Bildschirm
* aktualisiert und die Inhalt fortan als negativ interpretiert.
* Zeigt der Bildschirm bereits einen negativen Wert mit führendem Minus an, dann wird dieses
* entfernt und der Inhalt fortan als positiv interpretiert.
*/
public void pressNegativeKey() {
screen = screen.startsWith("-") ? screen.substring(1) : "-" + screen;
}

/**
* Empfängt den Befehl der gedrückten "="-Taste.
* Wurde zuvor keine Operationstaste gedrückt, passiert nichts.
* Wurde zuvor eine binäre Operationstaste gedrückt und zwei Operanden eingegeben, wird das
* Ergebnis der Operation angezeigt. Falls hierbei eine Division durch Null auftritt, wird "Error" angezeigt.
* Wird die Taste weitere Male gedrückt (ohne andere Tasten dazwischen), so wird die letzte
* Operation (ggf. inklusive letztem Operand) erneut auf den aktuellen Bildschirminhalt angewandt
* und das Ergebnis direkt angezeigt.
*/
public void pressEqualsKey() {
// Überprüfung - ob eine Operation ausgewählt wurde
if (latestOperation.isEmpty()) {
return; // Wenn keine Operation vorhanden ist passiert nichts
}

double result;
double divisor = Double.parseDouble(screen);

// Durchführung der Berechnung
switch(latestOperation) {
case "+" -> result = latestValue + divisor;
case "-" -> result = latestValue - divisor;
case "x" -> result = latestValue * divisor;
case "/" -> {
if (divisor == 0) { // Division durch Null
screen = "Error";
return; // Methode verlassen
}
result = latestValue / divisor;
}
default -> throw new IllegalArgumentException("Ungültige Operation");
}

// Ergebnis auf den Bildschirm setzen
screen = Double.toString(result);

// Formatierung des Bildschirms
if (screen.endsWith(".0")) {
screen = screen.substring(0, screen.length() - 2); // Entfernt .0
}
if (screen.contains(".") && screen.length() > 11) {
screen = screen.substring(0, 10); // Begrenzung auf 10 Zeichen
} //commit 2-5 - 2 rote tests mit bugfixes -p
}

}
45 changes: 44 additions & 1 deletion app/src/test/java/htw/berlin/prog2/ha1/CalculatorTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,48 @@ void testMultipleDecimalDots() {


//TODO hier weitere Tests erstellen
}
@Test
@DisplayName ("soll den Bildschirm auf 0 zurücksetzen, wenn die Clear-Taste = 0 gedrückt wird")
void testClearScreen() {
Calculator calc = new Calculator();

calc.pressDigitKey(1);//1 eingeben
calc.pressDigitKey(6);//6 eingeben und dann clear taste drücken
calc.pressClearKey();// clear taste drücken

String expected = "0";// ergebnis ist 0
String actual = calc.readScreen(); //commit 1 -

assertEquals(expected, actual);
}
@Test
@DisplayName ("soll 'Error' anzeigen, wenn ein negativer Wert durch Null geteilt wird")
void testNegativeDivisionByZero() {
Calculator calc = new Calculator();

calc.pressDigitKey(9);// 9 eingeben
calc.pressNegativeKey(); // -9 eingeben
calc.pressBinaryOperationKey("/");// geteilt eingeben
calc.pressDigitKey(0); // geteilt 0 eingeben
calc.pressEqualsKey(); // ergebnis berechnen = error

String expected = "Error"; //zeigt error an
String actual = calc.readScreen(); //commit 2 - 1/2 -

assertEquals(expected, actual);
}
@Test
@DisplayName ("soll 'Error' ausgeben, wenn der Kehrwert von 0 ermittelt wird")
void testInverseWithoutValue() {
Calculator calc = new Calculator();

calc.pressDigitKey(0); // 0 eingeben
calc.pressUnaryOperationKey("1/x"); // 1/x taste drücken = 1 durch 0 ist nicht definiert

String expected = "Error"; // zeigt error an
String actual = calc.readScreen(); //commit 2 - 2/2 p

assertEquals(expected, actual);
}

}