diff --git a/README.md b/README.md
index 6f9f289..2007bd6 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
# java.math.expression.parser
java math expression parser is a maven project that lets you parse or evaluate math expressions.
-This algorithm does not use a decision tree. It is a kind of Recursive Ascent Parser (https://en.wikipedia.org/wiki/Recursive_ascent_parser). In fact, it is LR parser (Left-Right Parser) without backtracking.
+This algorithm does not use a decision tree. It is a kind of Recursive Descent Parser (https://en.wikipedia.org/wiki/Recursive_descent_parser). In fact, it is LR parser (Left-Right Parser) without backtracking.
This algorithm is faster than JEP math expresion parser!!! If you compare java.math.expression.parse and JEP, this algorithm only needs 25% of the time to parse the same expression as JEP. With other algorithms that use trees like:
@@ -90,14 +90,17 @@ This algorithm is faster than JEP math expresion parser!!! If you compare java.m
These are the results for the version 3.0 (master). You can check the speedTests in the project
- Parser.simpleEval("6.5*7.8^2.3 + (3.5^3+7/2)^3 -(5*4/(2-3))*4 + 6.5*7.8^2.3 + (3.5^3+7/2)^3 -(5*4/(2-3))*4
- + 6.5*7.8^2.3 + (3.5^3+7/2)^3 -(5*4/(2-3))*4 + 6.5*7.8^2.3 + (3.5^3+7/2)^3 -(5*4/(2-3))*4");
+ Parser.simpleEval("6.5*7.8^2.3 + (3.5^3+7/2)^3 -(5*4/(2-3))*4 + 6.5*7.8^2.3
+ + (3.5^3+7/2)^3 -(5*4/(2-3))*4 + 6.5*7.8^2.3 + (3.5^3+7/2)^3
+ -(5*4/(2-3))*4 + 6.5*7.8^2.3 + (3.5^3+7/2)^3 -(5*4/(2-3))*4");
CPU: i7-6500U
- test 1: one execution: 4ms
+ test 1: one execution: 3ms
test 2: 100000 executions : 2100 ms --> mean time 0.021 ms per execution
- test 3: one million executions: 16500 ms --> mean time 0.0165 ms per execution
+ (with graalvm-jdk-17.0.8+9.1 the total time is 754ms --> 0.00754 per execution)
+ test 3: one million executions: 16500 ms --> mean time 0.0165 ms per execution
+ (with graalvm-jdk-17.0.8+9.1 the total time is 7980ms --> 0,00798 per execution)
This version is compiled for Java 1.6
diff --git a/pom.xml b/pom.xml
index 4f5b566..7fd17c3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
com.expression.parsercom.expression.parserjar
- 3.0.0
+ 3.3.0com.expression.parser
diff --git a/src/main/java/com/expression/parser/function/ComplexFunction.java b/src/main/java/com/expression/parser/function/ComplexFunction.java
index b5bc594..739b0cb 100644
--- a/src/main/java/com/expression/parser/function/ComplexFunction.java
+++ b/src/main/java/com/expression/parser/function/ComplexFunction.java
@@ -6,7 +6,6 @@
import com.expression.parser.ParserManager;
import com.expression.parser.exception.CalculatorException;
-// TODO: Auto-generated Javadoc
/**
* The Class ComplexFunction.
*/
@@ -90,7 +89,7 @@ private Complex eval(final String f, final List values, final List= '0' && character <= '9') {
hasNumber = true;
- number = number + character;
+ number += character;
if (i == (f.length() - 1)) {
value = new Complex(new Double(number), 0);
number = "";
@@ -103,28 +102,28 @@ private Complex eval(final String f, final List values, final List values, final List values, final List values, final List values, final List values, final List values, final List values, final List values, final List values, final List 0)) {
- number = number + character;
+ number += character;
}
} else if (character == '(') {
@@ -265,39 +264,39 @@ private Complex eval(final String f, final List values, final List values, final List values, final List values, final List values, final List= '0' && character <= '9') {
hasNumber = true;
- number = number + character;
+ number += character;
if (i == (f_x.length() - 1)) {
value = new Double(number).doubleValue();
number = "";
@@ -87,19 +87,19 @@ private double eval(final String f_x, final double xi) throws CalculatorExceptio
final Double numb = new Double(number);
final String new_f_x = f_x.substring(i + 1, f_x.length());
value = numb + eval(new_f_x, xi);
- i = i + new_f_x.length();
+ i += new_f_x.length();
hasNumber = false;
number = "";
} else if (hasFunction) {
final String new_f_x = f_x.substring(i + 1, f_x.length());
value = eval(function, xi) + eval(new_f_x, xi);
- i = i + new_f_x.length();
+ i += new_f_x.length();
hasFunction = false;
function = "";
} else {
final String new_f_x = f_x.substring(i + 1, f_x.length());
value = value + eval(new_f_x, xi);
- i = i + new_f_x.length();
+ i += new_f_x.length();
}
} else if (character == '*') {
@@ -108,19 +108,19 @@ private double eval(final String f_x, final double xi) throws CalculatorExceptio
final Double numb = new Double(number);
final String new_f_x = nextFunction(f_x.substring(i + 1, f_x.length()));
value = numb * eval(new_f_x, xi);
- i = i + new_f_x.length();
+ i += new_f_x.length();
hasNumber = false;
number = "";
} else if (hasFunction) {
final String new_f_x = nextFunction(f_x.substring(i + 1, f_x.length()));
value = eval(function, xi) * eval(new_f_x, xi);
- i = i + new_f_x.length();
+ i += new_f_x.length();
hasFunction = false;
function = "";
} else {
final String new_f_x = nextFunction(f_x.substring(i + 1, f_x.length()));
value = value * eval(new_f_x, xi);
- i = i + new_f_x.length();
+ i += new_f_x.length();
}
} else if (character == '-') {
@@ -129,19 +129,19 @@ private double eval(final String f_x, final double xi) throws CalculatorExceptio
final Double numb = new Double(number);
final String new_f_x = nextMinusFunction(f_x.substring(i + 1, f_x.length()));
value = numb - eval(new_f_x, xi);
- i = i + new_f_x.length();
+ i += new_f_x.length();
hasNumber = false;
number = "";
} else if (hasFunction) {
final String new_f_x = nextMinusFunction(f_x.substring(i + 1, f_x.length()));
value = eval(function, xi) - eval(new_f_x, xi);
- i = i + new_f_x.length();
+ i += new_f_x.length();
hasFunction = false;
function = "";
} else {
final String new_f_x = nextMinusFunction(f_x.substring(i + 1, f_x.length()));
value = value - eval(new_f_x, xi);
- i = i + new_f_x.length();
+ i += new_f_x.length();
}
} else if (character == '/') {
@@ -150,19 +150,19 @@ private double eval(final String f_x, final double xi) throws CalculatorExceptio
final Double numb = new Double(number);
final String new_f_x = nextFunction(f_x.substring(i + 1, f_x.length()));
value = numb / eval(new_f_x, xi);
- i = i + new_f_x.length();
+ i += new_f_x.length();
hasNumber = false;
number = "";
} else if (hasFunction) {
final String new_f_x = nextFunction(f_x.substring(i + 1, f_x.length()));
value = eval(function, xi) / eval(new_f_x, xi);
- i = i + new_f_x.length();
+ i += new_f_x.length();
hasFunction = false;
function = "";
} else {
final String new_f_x = nextFunction(f_x.substring(i + 1, f_x.length()));
value = value / eval(new_f_x, xi);
- i = i + new_f_x.length();
+ i += new_f_x.length();
}
} else if (character == '^') {
@@ -170,20 +170,20 @@ private double eval(final String f_x, final double xi) throws CalculatorExceptio
if (hasNumber) {
final Double numb = new Double(number);
final String new_f_x = nextFunction(f_x.substring(i + 1, f_x.length()));
- value = Math.pow(numb.doubleValue(), eval(new_f_x, xi));
- i = i + new_f_x.length();
+ value = StrictMath.pow(numb.doubleValue(), eval(new_f_x, xi));
+ i += new_f_x.length();
hasNumber = false;
number = "";
} else if (hasFunction) {
final String new_f_x = nextFunction(f_x.substring(i + 1, f_x.length()));
- value = Math.pow(eval(function, xi), eval(new_f_x, xi));
- i = i + new_f_x.length();
+ value = StrictMath.pow(eval(function, xi), eval(new_f_x, xi));
+ i += new_f_x.length();
hasFunction = false;
function = "";
} else {
final String new_f_x = nextFunction(f_x.substring(i + 1, f_x.length()));
- value = Math.pow(value, eval(new_f_x, xi));
- i = i + new_f_x.length();
+ value = StrictMath.pow(value, eval(new_f_x, xi));
+ i += new_f_x.length();
}
} else if (character == '.') {
@@ -192,7 +192,7 @@ private double eval(final String f_x, final double xi) throws CalculatorExceptio
throw new CalculatorException("The function is not well-formed");
}
if (hasNumber && (number.length() > 0)) {
- number = number + character;
+ number += character;
}
} else if (character == '(') {
@@ -202,65 +202,65 @@ private double eval(final String f_x, final double xi) throws CalculatorExceptio
final String new_f_x = f_x.substring(i + 1, nextBracket(f_x));
if (hasFunction) {
- if (function.equals(Constants.SIN)) {
+ if (Constants.SIN.equals(function)) {
if (degree) {
- value = Math.sin(Math.toRadians(eval(new_f_x, xi)));
+ value = StrictMath.sin(StrictMath.toRadians(eval(new_f_x, xi)));
} else {
- value = Math.sin(eval(new_f_x, xi));
+ value = StrictMath.sin(eval(new_f_x, xi));
}
- } else if (function.equals(Constants.COS)) {
+ } else if (Constants.COS.equals(function)) {
if (degree) {
- value = Math.cos(Math.toRadians(eval(new_f_x, xi)));
+ value = StrictMath.cos(StrictMath.toRadians(eval(new_f_x, xi)));
} else {
- value = Math.cos(eval(new_f_x, xi));
+ value = StrictMath.cos(eval(new_f_x, xi));
}
- } else if (function.equals(Constants.TAN)) {
+ } else if (Constants.TAN.equals(function)) {
if (degree) {
- value = Math.tan(Math.toRadians(eval(new_f_x, xi)));
+ value = StrictMath.tan(StrictMath.toRadians(eval(new_f_x, xi)));
} else {
- value = Math.tan(eval(new_f_x, xi));
+ value = StrictMath.tan(eval(new_f_x, xi));
}
- } else if (function.equals(Constants.SINH)) {
- value = Math.sinh(eval(new_f_x, xi));
+ } else if (Constants.SINH.equals(function)) {
+ value = StrictMath.sinh(eval(new_f_x, xi));
- } else if (function.equals(Constants.COSH)) {
- value = Math.cosh(eval(new_f_x, xi));
+ } else if (Constants.COSH.equals(function)) {
+ value = StrictMath.cosh(eval(new_f_x, xi));
- } else if (function.equals(Constants.TANH)) {
- value = Math.tanh(eval(new_f_x, xi));
+ } else if (Constants.TANH.equals(function)) {
+ value = StrictMath.tanh(eval(new_f_x, xi));
- } else if (function.equals(Constants.ASIN)) {
+ } else if (Constants.ASIN.equals(function)) {
if (degree) {
- value = Math.asin(eval(new_f_x, xi)) * (180 / Math.PI);
+ value = StrictMath.asin(eval(new_f_x, xi)) * (180 / StrictMath.PI);
} else {
- value = Math.asin(eval(new_f_x, xi));
+ value = StrictMath.asin(eval(new_f_x, xi));
}
- } else if (function.equals(Constants.ACOS)) {
+ } else if (Constants.ACOS.equals(function)) {
if (degree) {
- value = Math.acos(eval(new_f_x, xi)) * (180 / Math.PI);
+ value = StrictMath.acos(eval(new_f_x, xi)) * (180 / StrictMath.PI);
} else {
- value = Math.acos(eval(new_f_x, xi));
+ value = StrictMath.acos(eval(new_f_x, xi));
}
- } else if (function.equals(Constants.ATAN)) {
+ } else if (Constants.ATAN.equals(function)) {
if (degree) {
- value = Math.atan(eval(new_f_x, xi)) * (180 / Math.PI);
+ value = StrictMath.atan(eval(new_f_x, xi)) * (180 / StrictMath.PI);
} else {
- value = Math.atan(eval(new_f_x, xi));
+ value = StrictMath.atan(eval(new_f_x, xi));
}
- } else if (function.equals(Constants.LN)) {
- value = Math.log(eval(new_f_x, xi));
- } else if (function.equals(Constants.LOG)) {
- value = Math.log10(eval(new_f_x, xi));
- } else if (function.equals(Constants.SQRT)) {
- value = Math.sqrt(eval(new_f_x, xi));
- } else if (function.equals(Constants.CBRT)) {
- value = Math.cbrt(eval(new_f_x, xi));
+ } else if (Constants.LN.equals(function)) {
+ value = StrictMath.log(eval(new_f_x, xi));
+ } else if (Constants.LOG.equals(function)) {
+ value = StrictMath.log10(eval(new_f_x, xi));
+ } else if (Constants.SQRT.equals(function)) {
+ value = StrictMath.sqrt(eval(new_f_x, xi));
+ } else if (Constants.CBRT.equals(function)) {
+ value = StrictMath.cbrt(eval(new_f_x, xi));
} else {
throw new CalculatorException("The function is not well-formed");
}
@@ -271,35 +271,34 @@ private double eval(final String f_x, final double xi) throws CalculatorExceptio
} else {
value = eval(new_f_x, xi);
}
- i = i + new_f_x.length() + 1;
-
- } else if (character == ')') {
- throw new CalculatorException(" '(' is not finished ");
-
- } else if (character == ' ') {
+ i += new_f_x.length() + 1;
} else if (isValidCharacter(character)) {
function = function + character;
hasFunction = true;
if (i == (f_x.length() - 1)) {
- if (function.equals(Constants.E)) {
- value = Math.E;
- } else if (function.equals(Constants.PI)) {
- value = Math.PI;
+ if (Constants.E.equals(function)) {
+ value = StrictMath.E;
+ } else if (Constants.PI.equals(function)) {
+ value = StrictMath.PI;
} else if (function.length() == 1) {
value = xi;
} else {
throw new CalculatorException("function is not well defined");
}
}
+
+ } else if (character == ')') {
+ throw new CalculatorException(" '(' is not finished ");
+
+ } else if (character == ' ') {
+
} else {
throw new CalculatorException("Invalid character:" + character);
}
-
}
return value;
-
}
/**
@@ -309,30 +308,26 @@ private double eval(final String f_x, final double xi) throws CalculatorExceptio
* @return the string
* @throws CalculatorException the calculator exception
*/
- private String nextFunction(String f_x) throws CalculatorException {
+ private String nextFunction(final String f_x) throws CalculatorException {
String result = "";
- f_x = f_x.trim().toLowerCase();
for (int i = 0; i < f_x.length(); i++) {
final char character = f_x.charAt(i);
- if (character == '+' || character == '*' || character == '-' || character == '/') {
+ if (isValidNumericAndCharacter(character)) {
+ result += character;
+ } else if (character == '+' || character == '*' || character == '-' || character == '/') {
i = f_x.length();
- } else if (character == '^') {
- result = result + character;
- } else if (character == '.') {
- result = result + character;
+ } else if (character == '.' || character == '^') {
+ result += character;
} else if (character == '(') {
final String new_f_x = f_x.substring(i, nextBracket(f_x) + 1);
- result = result + new_f_x;
+ result += new_f_x;
i = (i + new_f_x.length()) - 1;
} else if (character == ')') {
throw new CalculatorException(" '(' is not finished ");
-
} else if (character == ' ') {
- result = result + character;
- } else if (isValidNumericAndCharacter(character)) {
- result = result + character;
+ result += character;
} else {
throw new CalculatorException("Invalid character:" + character);
}
@@ -352,28 +347,20 @@ private String nextMinusFunction(final String f_x) throws CalculatorException {
for (int i = 0; i < f_x.length(); i++) {
final char character = f_x.charAt(i);
- if (character == '+') {
+ if (isValidNumericAndCharacter(character)) {
+ result += character;
+ } else if (character == '+' || character == '-') {
i = f_x.length();
- } else if (character == '*') {
- result = result + character;
- } else if (character == '-') {
- i = f_x.length();
- } else if (character == '/') {
- result = result + character;
- } else if (character == '^') {
- result = result + character;
- } else if (character == '.') {
- result = result + character;
+ } else if (character == '*' || character == '/' || character == '.' || character == '^') {
+ result += character;
} else if (character == '(') {
final String new_f_x = f_x.substring(i, nextBracket(f_x) + 1);
- result = result + new_f_x;
+ result += new_f_x;
i = (i + new_f_x.length()) - 1;
} else if (character == ')') {
throw new CalculatorException(" '(' is not finished ");
} else if (character == ' ') {
- result = result + character;
- } else if (isValidNumericAndCharacter(character)) {
- result = result + character;
+ result += character;
} else {
throw new CalculatorException("Invalid character:" + character);
}
@@ -430,7 +417,6 @@ private int nextBracket(final String f_x) throws CalculatorException {
if (count == 0) {
return i;
}
-
} else {
result = i;
}
diff --git a/src/main/java/com/expression/parser/function/FunctionXs.java b/src/main/java/com/expression/parser/function/FunctionXs.java
index 384ef79..0322cfa 100644
--- a/src/main/java/com/expression/parser/function/FunctionXs.java
+++ b/src/main/java/com/expression/parser/function/FunctionXs.java
@@ -86,7 +86,7 @@ private double eval(final String f, final List values, final List= '0' && character <= '9') {
hasNumber = true;
- number = number + character;
+ number += character;
if (i == (f.length() - 1)) {
value = new Double(number).doubleValue();
number = "";
@@ -99,20 +99,20 @@ private double eval(final String f, final List values, final List values, final List values, final List values, final List values, final List values, final List 0)) {
- number = number + character;
+ number += character;
}
} else if (character == '(') {
@@ -217,61 +217,61 @@ private double eval(final String f, final List values, final List values, final List values, final ListpFad - Phonifier reborn
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.