Skip to content

Commit

Permalink
Fix #1188 sign calculator floating point errors
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinthegreat1 committed Feb 24, 2025
1 parent 54b1127 commit bc33f40
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import net.minecraft.client.gui.DrawContext;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import org.jetbrains.annotations.VisibleForTesting;

import java.text.NumberFormat;
import java.util.Locale;
Expand All @@ -26,29 +27,34 @@ public static void renderCalculator(DrawContext context, String message, int ren
if (message.startsWith("=")) {
message = message.substring(1);
}
//only update output if new input
if (!message.equals(lastInput)) { //
try {
output = Calculator.calculate(message);
} catch (Exception e) {
output = -1;
}
}
calculate(message);

render(context, message, renderX, renderY);

lastInput = message;
}

public static String getNewValue(Boolean isPrice) {
@VisibleForTesting
public static void calculate(String message) {
//only update output if new input
if (!message.equals(lastInput)) {
try {
output = Calculator.calculate(message);
} catch (Exception e) {
output = -1;
}
}
}

public static String getNewValue(boolean isPrice) {
if (output == -1) {
//if mode is not activated or just invalid equation return what the user typed in
return lastInput;
}

//price can except decimals and exponents
if (isPrice) {
return String.valueOf(output);
return String.valueOf(Math.round(output * 100d) / 100d);
}
//amounts want an integer number so round
return Long.toString(Math.round(output));
Expand Down
53 changes: 32 additions & 21 deletions src/test/java/de/hysky/skyblocker/utils/CalculatorTest.java
Original file line number Diff line number Diff line change
@@ -1,31 +1,42 @@
package de.hysky.skyblocker.utils;

import de.hysky.skyblocker.skyblock.calculators.SignCalculator;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

public class CalculatorTest {
@Test
void testShorthands() {
Assertions.assertEquals(Calculator.calculate("1k"), 1000);
Assertions.assertEquals(Calculator.calculate("0.12k"), 120);
Assertions.assertEquals(Calculator.calculate("1k + 0.12k"), 1120);
Assertions.assertEquals(Calculator.calculate("1 + 1s + 1k + 1m + 1b"), 1001001065);
}
@Test
void testShorthands() {
assertCalculation(1000, "1k");
assertCalculation(120, "0.12k");
assertCalculation(1120, "1k + 0.12k");
assertCalculation(1001001065, "1 + 1s + 1k + 1m + 1b");
}

@Test
void testPrecedence() {
Assertions.assertEquals(Calculator.calculate("5 + 2 * 2"), 9);
Assertions.assertEquals(Calculator.calculate("5 - 2 / 2"), 4);
Assertions.assertEquals(Calculator.calculate("5 * (1 + 2)"), 15);
}
@Test
void testPrecedence() {
assertCalculation(9, "5 + 2 * 2");
assertCalculation(4, "5 - 2 / 2");
assertCalculation(15, "5 * (1 + 2)");
}

@Test
void testImplicitMultiplication() {
Assertions.assertEquals(Calculator.calculate("5(2 + 2)"), 20);
}
@Test
void testImplicitMultiplication() {
assertCalculation(20, "5(2 + 2)");
}

@Test
void testImplicitClosingParenthesis() {
Assertions.assertEquals(Calculator.calculate("5(2 + 2"), 20);
}
@Test
void testImplicitClosingParenthesis() {
assertCalculation(20, "5(2 + 2");
}

@Test
void testFloatingPointError() {
SignCalculator.calculate("262.6m");
Assertions.assertEquals("2.626E8", SignCalculator.getNewValue(true));
}

private void assertCalculation(double expected, String input) {
Assertions.assertEquals(expected, Calculator.calculate(input));
}
}

0 comments on commit bc33f40

Please sign in to comment.