Skip to content

Commit 03d330a

Browse files
committed
Add SIGMA custom function to EvalEx for sigma summation support
1 parent 49ba4db commit 03d330a

1 file changed

Lines changed: 51 additions & 4 deletions

File tree

core/src/main/java/cn/superiormc/ultimateshop/utils/MathUtil.java

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,13 @@
22

33
import cn.superiormc.ultimateshop.managers.ConfigManager;
44
import cn.superiormc.ultimateshop.managers.ErrorManager;
5+
import com.ezylang.evalex.EvaluationException;
56
import com.ezylang.evalex.Expression;
7+
import com.ezylang.evalex.config.ExpressionConfiguration;
8+
import com.ezylang.evalex.data.EvaluationValue;
9+
import com.ezylang.evalex.functions.AbstractFunction;
10+
import com.ezylang.evalex.functions.FunctionParameter;
11+
import com.ezylang.evalex.parser.Token;
612

713
import java.math.BigDecimal;
814
import java.math.RoundingMode;
@@ -18,13 +24,21 @@ public class MathUtil {
1824

1925
public static DecimalFormat decimalFormat;
2026

27+
private static ExpressionConfiguration expressionConfig;
28+
29+
private static final int SIGMA_MAX_ITERATIONS = 100000;
30+
2131
public static void init() {
22-
scale = ConfigManager.configManager.getInt("math.scale", 2);
32+
scale = ConfigManager.configManager.getInt("math.scale", 2);
2333
String integerPattern = ConfigManager.configManager.getString("number-display.format.integer", "#,##0");
2434
String decimalPattern = ConfigManager.configManager.getString("number-display.format.decimal", "#,##0.00##########");
2535
DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(Locale.US);
2636
integerFormat = new DecimalFormat(integerPattern, symbols);
2737
decimalFormat = new DecimalFormat(decimalPattern, symbols);
38+
39+
expressionConfig = ExpressionConfiguration.builder()
40+
.function("SIGMA", new SigmaFunction())
41+
.build();
2842
}
2943

3044
public static double multiply(double left, double right) {
@@ -57,9 +71,10 @@ public static BigDecimal doCalculate(String mathStr, int scale) {
5771
if (!ConfigManager.configManager.getBoolean("math.enabled")) {
5872
return new BigDecimal(mathStr);
5973
}
60-
return new Expression(mathStr).evaluate().getNumberValue().setScale(scale, RoundingMode.HALF_UP);
61-
}
62-
catch (Throwable throwable) {
74+
return new Expression(mathStr, expressionConfig).evaluate()
75+
.getNumberValue()
76+
.setScale(scale, RoundingMode.HALF_UP);
77+
} catch (Throwable throwable) {
6378
if (ConfigManager.configManager.getBoolean("debug")) {
6479
throwable.printStackTrace();
6580
}
@@ -69,4 +84,36 @@ public static BigDecimal doCalculate(String mathStr, int scale) {
6984
return BigDecimal.ZERO;
7085
}
7186
}
87+
88+
@FunctionParameter(name = "start")
89+
@FunctionParameter(name = "end")
90+
@FunctionParameter(name = "body")
91+
public static class SigmaFunction extends AbstractFunction {
92+
93+
@Override
94+
public EvaluationValue evaluate(EvaluationValue... args) {
95+
int start = args[0].getNumberValue().intValue();
96+
int end = args[1].getNumberValue().intValue();
97+
String body = args[2].getStringValue();
98+
99+
if (start > end) {
100+
return EvaluationValue.numberValue(BigDecimal.ZERO);
101+
}
102+
103+
int count = end - start + 1;
104+
if (count > SIGMA_MAX_ITERATIONS) {
105+
throw new EvaluationException(
106+
new Token(0, body),
107+
"SIGMA: too many iterations (" + count + "), maximum is " + SIGMA_MAX_ITERATIONS);
108+
}
109+
110+
BigDecimal sum = BigDecimal.ZERO;
111+
for (int i = start; i <= end; i++) {
112+
Expression subExpr = new Expression(body, expressionConfig)
113+
.with("i", BigDecimal.valueOf(i));
114+
sum = sum.add(subExpr.evaluate().getNumberValue());
115+
}
116+
return EvaluationValue.numberValue(sum);
117+
}
118+
}
72119
}

0 commit comments

Comments
 (0)