From fd98e0040d84164f28a48d5f2d454fe11ae366c0 Mon Sep 17 00:00:00 2001 From: u9g Date: Thu, 20 Oct 2022 21:02:54 -0400 Subject: [Calculator] Add exponent operator and % postfix (#374) * [Calculator] Add exponent operator * [Calculator] Add percent postfix * Add new suggestions --- .../notenoughupdates/util/Calculator.java | 33 ++++++++++++++++++++-- 1 file 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 op = new ArrayDeque<>(); List 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, -- cgit