mirror of
https://github.com/BentoBoxWorld/Level.git
synced 2024-11-25 20:25:28 +01:00
Added test class for EquationEvaluator
This commit is contained in:
parent
2b373f62d9
commit
76e0bad88a
@ -3,119 +3,119 @@ package world.bentobox.level.calculators;
|
|||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author tastybento
|
* Utility class to evaluate equations
|
||||||
*/
|
*/
|
||||||
public class EquationEvaluator {
|
public class EquationEvaluator {
|
||||||
|
|
||||||
private static class Parser {
|
private static class Parser {
|
||||||
private final String input;
|
private final String input;
|
||||||
private int pos = -1;
|
private int pos = -1;
|
||||||
private int currentChar;
|
private int currentChar;
|
||||||
|
|
||||||
public Parser(String input) {
|
@SuppressWarnings("unused")
|
||||||
this.input = input;
|
private Parser() {
|
||||||
moveToNextChar();
|
throw new IllegalStateException("Utility class");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void moveToNextChar() {
|
public Parser(String input) {
|
||||||
currentChar = (++pos < input.length()) ? input.charAt(pos) : -1;
|
this.input = input;
|
||||||
}
|
moveToNextChar();
|
||||||
|
}
|
||||||
|
|
||||||
private boolean tryToEat(int charToEat) {
|
private void moveToNextChar() {
|
||||||
while (currentChar == ' ')
|
currentChar = (++pos < input.length()) ? input.charAt(pos) : -1;
|
||||||
moveToNextChar();
|
}
|
||||||
if (currentChar == charToEat) {
|
|
||||||
moveToNextChar();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double evaluate() throws ParseException {
|
private boolean tryToEat(int charToEat) {
|
||||||
double result = parseExpression();
|
while (currentChar == ' ') {
|
||||||
if (pos < input.length()) {
|
moveToNextChar();
|
||||||
throw new ParseException("Unexpected character: " + (char) currentChar, pos);
|
}
|
||||||
}
|
if (currentChar == charToEat) {
|
||||||
return result;
|
moveToNextChar();
|
||||||
}
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private double parseExpression() throws ParseException {
|
public double evaluate() throws ParseException {
|
||||||
double result = parseTerm();
|
double result = parseExpression();
|
||||||
while (true) {
|
if (pos < input.length()) {
|
||||||
if (tryToEat('+'))
|
throw new ParseException("Unexpected character: " + (char) currentChar, pos);
|
||||||
result += parseTerm();
|
}
|
||||||
else if (tryToEat('-'))
|
return result;
|
||||||
result -= parseTerm();
|
}
|
||||||
else
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private double parseFactor() throws ParseException {
|
private double parseExpression() throws ParseException {
|
||||||
if (tryToEat('+'))
|
double result = parseTerm();
|
||||||
return parseFactor(); // unary plus
|
while (true) {
|
||||||
if (tryToEat('-'))
|
if (tryToEat('+')) {
|
||||||
return -parseFactor(); // unary minus
|
result += parseTerm();
|
||||||
|
} else if (tryToEat('-')) {
|
||||||
|
result -= parseTerm();
|
||||||
|
} else {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
double x;
|
private double parseFactor() throws ParseException {
|
||||||
int startPos = this.pos;
|
if (tryToEat('+')) {
|
||||||
if (tryToEat('(')) { // parentheses
|
return parseFactor(); // unary plus
|
||||||
x = parseExpression();
|
}
|
||||||
tryToEat(')');
|
if (tryToEat('-')) {
|
||||||
} else if ((currentChar >= '0' && currentChar <= '9') || currentChar == '.') { // numbers
|
return -parseFactor(); // unary minus
|
||||||
while ((currentChar >= '0' && currentChar <= '9') || currentChar == '.')
|
}
|
||||||
moveToNextChar();
|
double x;
|
||||||
x = Double.parseDouble(input.substring(startPos, this.pos));
|
int startPos = this.pos;
|
||||||
} else if (currentChar >= 'a' && currentChar <= 'z') { // functions
|
if (tryToEat('(')) { // parentheses
|
||||||
while (currentChar >= 'a' && currentChar <= 'z')
|
x = parseExpression();
|
||||||
moveToNextChar();
|
tryToEat(')');
|
||||||
String func = input.substring(startPos, this.pos);
|
} else if ((currentChar >= '0' && currentChar <= '9') || currentChar == '.') { // numbers
|
||||||
x = parseFactor();
|
while ((currentChar >= '0' && currentChar <= '9') || currentChar == '.') {
|
||||||
switch (func) {
|
moveToNextChar();
|
||||||
case "sqrt":
|
}
|
||||||
x = Math.sqrt(x);
|
x = Double.parseDouble(input.substring(startPos, this.pos));
|
||||||
break;
|
} else if (currentChar >= 'a' && currentChar <= 'z') { // functions
|
||||||
case "sin":
|
while (currentChar >= 'a' && currentChar <= 'z') {
|
||||||
x = Math.sin(Math.toRadians(x));
|
moveToNextChar();
|
||||||
break;
|
}
|
||||||
case "cos":
|
String func = input.substring(startPos, this.pos);
|
||||||
x = Math.cos(Math.toRadians(x));
|
x = parseFactor();
|
||||||
break;
|
x = switch (func) {
|
||||||
case "tan":
|
case "sqrt" -> Math.sqrt(x);
|
||||||
x = Math.tan(Math.toRadians(x));
|
case "sin" -> Math.sin(Math.toRadians(x));
|
||||||
break;
|
case "cos" -> Math.cos(Math.toRadians(x));
|
||||||
case "log":
|
case "tan" -> Math.tan(Math.toRadians(x));
|
||||||
x = Math.log(x);
|
case "log" -> Math.log(x);
|
||||||
break;
|
default -> throw new ParseException("Unknown function: " + func, startPos);
|
||||||
default:
|
};
|
||||||
throw new ParseException("Unknown function: " + func, startPos);
|
} else {
|
||||||
}
|
throw new ParseException("Unexpected: " + (char) currentChar, startPos);
|
||||||
} else {
|
}
|
||||||
throw new ParseException("Unexpected: " + (char) currentChar, startPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tryToEat('^'))
|
if (tryToEat('^')) {
|
||||||
x = Math.pow(x, parseFactor()); // exponentiation
|
x = Math.pow(x, parseFactor()); // exponentiation
|
||||||
|
}
|
||||||
|
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
private double parseTerm() throws ParseException {
|
private double parseTerm() throws ParseException {
|
||||||
double x = parseFactor();
|
double x = parseFactor();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (tryToEat('*'))
|
if (tryToEat('*'))
|
||||||
x *= parseFactor(); // multiplication
|
x *= parseFactor(); // multiplication
|
||||||
else if (tryToEat('/'))
|
else if (tryToEat('/'))
|
||||||
x /= parseFactor(); // division
|
x /= parseFactor(); // division
|
||||||
else
|
else
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double eval(final String equation) throws ParseException {
|
public static double eval(final String equation) throws ParseException {
|
||||||
return new Parser(equation).evaluate();
|
return new Parser(equation).evaluate();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
package world.bentobox.level.calculators;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the equation evaluation
|
||||||
|
*/
|
||||||
|
public class EquationEvaluatorTest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test method for {@link world.bentobox.level.calculators.EquationEvaluator#eval(java.lang.String)}.
|
||||||
|
* @throws ParseException
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testEval() throws ParseException {
|
||||||
|
assertEquals(4D, EquationEvaluator.eval("2+2"), 0D);
|
||||||
|
assertEquals(0D, EquationEvaluator.eval("2-2"), 0D);
|
||||||
|
assertEquals(1D, EquationEvaluator.eval("2/2"), 0D);
|
||||||
|
assertEquals(4D, EquationEvaluator.eval("2*2"), 0D);
|
||||||
|
assertEquals(8D, EquationEvaluator.eval("2+2+2+2"), 0D);
|
||||||
|
assertEquals(5D, EquationEvaluator.eval("2.5+2.5"), 0D);
|
||||||
|
assertEquals(1.414, EquationEvaluator.eval("sqrt(2)"), 0.001D);
|
||||||
|
assertEquals(3.414, EquationEvaluator.eval("2 + sqrt(2)"), 0.001D);
|
||||||
|
assertEquals(0D, EquationEvaluator.eval("sin(0)"), 0.1D);
|
||||||
|
assertEquals(1D, EquationEvaluator.eval("cos(0)"), 0.1D);
|
||||||
|
assertEquals(0D, EquationEvaluator.eval("tan(0)"), 0.1D);
|
||||||
|
assertEquals(0D, EquationEvaluator.eval("log(1)"), 0.1D);
|
||||||
|
assertEquals(27D, EquationEvaluator.eval("3^3"), 0.D);
|
||||||
|
assertEquals(84.70332D, EquationEvaluator.eval("3^3 + 2 + 2.65 * (3 / 4) - sin(45) * log(10) + 55.344"),
|
||||||
|
0.0001D);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user