diff options
author | u9g <git@u9g.dev> | 2022-10-20 21:02:54 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-20 21:02:54 -0400 |
commit | fd98e0040d84164f28a48d5f2d454fe11ae366c0 (patch) | |
tree | 51c55087df2030dcc864ad6f6af7fa5b90c657b3 /src/main/java | |
parent | 58509dd21c282d4e0cf2b0efb6095fcef93b21a1 (diff) | |
download | NotEnoughUpdates-fd98e0040d84164f28a48d5f2d454fe11ae366c0.tar.gz NotEnoughUpdates-fd98e0040d84164f28a48d5f2d454fe11ae366c0.tar.bz2 NotEnoughUpdates-fd98e0040d84164f28a48d5f2d454fe11ae366c0.zip |
[Calculator] Add exponent operator and % postfix (#374)
* [Calculator] Add exponent operator
* [Calculator] Add percent postfix
* Add new suggestions
Diffstat (limited to 'src/main/java')
-rw-r--r-- | src/main/java/io/github/moulberry/notenoughupdates/util/Calculator.java | 33 |
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, |