aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/io
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/io')
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/Calculator.java33
1 files changed, 31 insertions, 2 deletions
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/Calculator.java b/src/main/java/io/github/moulberry/notenoughupdates/util/Calculator.java
index 10bfa6a9..b39a05f4 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/Calculator.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/Calculator.java
@@ -48,8 +48,8 @@ public class Calculator {
int tokenLength;
}
- static String binops = "+-*/x";
- static String postops = "mkbts";
+ static String binops = "+-*/^x";
+ static String postops = "mkbts%";
static String digits = "0123456789";
static void readDigitsInto(Token token, String source, boolean decimals) {
@@ -150,6 +150,8 @@ public class Calculator {
case "/":
case "x":
return 1;
+ case "^":
+ return 2;
}
throw new CalculatorException("Unknown operator " + token.operatorValue, token.tokenStart, token.tokenLength);
}
@@ -160,6 +162,7 @@ public class Calculator {
Deque<Token> op = new ArrayDeque<>();
List<Token> out = new ArrayList<>();
+ boolean nextMultiplyShouldBePower = false;
for (Token currentlyShunting : toShunt) {
switch (currentlyShunting.type) {
@@ -167,6 +170,17 @@ public class Calculator {
out.add(currentlyShunting);
break;
case BINOP:
+ Token next = toShunt.get(toShunt.indexOf(currentlyShunting) + 1);
+ if (currentlyShunting.operatorValue.equals("^")) {
+ if (next.numericValue > 999) {
+ throw new CalculatorException(next.numericValue + " is too large, pick a power less than 1000", next.tokenStart, next.tokenLength);
+ }
+ } else if (next != null && currentlyShunting.operatorValue.equals("*") && next.operatorValue != null && next.operatorValue.equals("*")) {
+ nextMultiplyShouldBePower = true;
+ continue;
+ } else if (nextMultiplyShouldBePower && currentlyShunting.operatorValue.equals("*")) {
+ currentlyShunting.operatorValue = "^";
+ }
int p = getPrecedence(currentlyShunting);
while (!op.isEmpty()) {
Token l = op.peek();
@@ -230,6 +244,18 @@ public class Calculator {
BigDecimal right = values.pop().setScale(2, RoundingMode.HALF_UP);
BigDecimal left = values.pop().setScale(2, RoundingMode.HALF_UP);
switch (command.operatorValue.intern()) {
+ case "^":
+ if (right.compareTo(new BigDecimal(1000)) >= 0) {
+ Token rightToken = rpnTokens.get(rpnTokens.indexOf(command) - 1);
+ throw new CalculatorException(right + " is too large, pick a power less than 1000", rightToken.tokenStart, rightToken.tokenLength);
+ }
+
+ if (right.doubleValue() != right.intValue()) {
+ Token rightToken = rpnTokens.get(rpnTokens.indexOf(command) - 1);
+ throw new CalculatorException(right + " has a decimal, pick a power that is non-decimal", rightToken.tokenStart, rightToken.tokenLength);
+ }
+ values.push(left.pow(right.intValue()).setScale(2, RoundingMode.HALF_UP));
+ break;
case "x":
case "*":
values.push(left.multiply(right).setScale(2, RoundingMode.HALF_UP));
@@ -280,6 +306,9 @@ public class Calculator {
case "t":
values.push(p.multiply(new BigDecimal("1000000000000")).setScale(2, RoundingMode.HALF_UP));
break;
+ case "%":
+ values.push(p.setScale(3, RoundingMode.HALF_UP).divide(new BigDecimal(100), RoundingMode.HALF_UP).setScale(2, RoundingMode.HALF_UP));
+ break;
default:
throw new CalculatorException(
"Unknown operation " + command.operatorValue,