Skip to content
tonyluken edited this page Nov 16, 2023 · 10 revisions

StringMathExpressionEvaluator

StringMathExpressionEvaluator is a Java class that provides methods for finding the numerical value of math expressions written as strings. The expressions can be composed of a series of numbers, operators, and/or functions. The example code snippet below shows how to use StringMathExpressionEvaluator to find the numerical value of six different math expressions (the last with a purposeful error):

    StringMathExpressionEvaluator smee = new StringMathExpressionEvaluator();
    String expression = "";
    double value;
    try {
        expression = "17.3*(2-0.145)/7";
        value = smee.evaluate(expression);
        System.out.println(expression " = " + value);

        expression = "sqrt(3^2 + 4^2)";
        value = smee.evaluate(expression);
        System.out.println(expression " = " + value);

        expression = "atan(1/sqrt(3))";
        smee.setDegreeMode(); //                <--- sets degree mode so atan will return its results in degrees rather than radians (the default)
        value = smee.evaluate(expression);
        System.out.println(expression " = " + value + " degrees");
        smee.setRadianMode(); //                <--- change back to radian mode
        value = smee.evaluate(expression);
        System.out.println(expression " = " + value + " radians");

        expression = "(6 + sqrt((-6)^2-4*1*8))/(2*1)";
        value = smee.evaluate(expression);
        System.out.println(expression " = " + value);

        expression = "(6 - sqrt((-6)^2-4*1*8))/(2*1)";
        value = smee.evaluate(expression);
        System.out.println(expression " = " + value);

        expression = "(6 - sqt((-6)^2-4*1*8))/(2*1)"; //   <--- sqrt misspelled here as sqt
        value = smee.evaluate(expression);
        System.out.println(expression " = " + value);
    }
    catch (InvalidMathExpressionException ex) {
        System.out.println(expression + " : " + ex.getMessage());
    }

When the above code executes, the following output results:

17.3*(2-0.145)/7 = 4.5845
sqrt(3^2 + 4^2) = 5.0
atan(1/sqrt(3)) = 30.000000000000004 degrees
atan(1/sqrt(3)) = 0.5235987755982989 radians
(6 + sqrt((-6)^2-4*1*8))/(2*1) = 4.0
(6 - sqrt((-6)^2-4*1*8))/(2*1) = 2.0
(6 - sqt((-6)^2-4*1*8))/(2*1) : Unknown function: sqt with one argument at index 5

StringMathExpressionEvaluator evaluates all math expressions using Java's double precision arithmetic. As a result, math expressions can evaluate to Double.NAN (for example, by taking the square root of a negative number or division of zero by zero), Double.NEGATIVE_INFINITY (for example, by division of a negative number by zero), or Double.POSITIVE_INFINITY (for example, by division of a positive number by zero). Also be aware of the usual caveats due to finite precision arithmetic when comparing numbers using the relational operators.

Numbers

A number is represented by a series of decimal digits '0' to '9' with a single optional decimal point '.' either before, after, or between the digits. At least one digit must be present. Scientific notation is also supported using the standard 'E' (or 'e') suffix followed by an optional sign followed by a series of decimal digits which represents a power of 10 multiplier. All numbers may be preceded by an optional sign. All numbers, regardless of whether they have a decimal point or not, are treated as Java doubles - no integer math here - "7/2" evaluates to floating point 3.5. Some examples of valid numbers are:

Number Floating point value
"2" 2.0
"17.3" 17.3
"+21" 21.0
"-2.3" -2.3
".3" 0.3
"-.05" -0.05
"2.99792458e8" 2.99792458x108
"2.99792458E+08" 2.99792458x108
"-2.99792458e+008" -2.99792458x108
"1.38065E-23" 1.38065x10-23

Operators

The table below lists the available operators and is ordered from highest to lowest precedence:

^ exponentiation, x^y is the same as the pow(x, y) function
+ - unary sign
* / % multiplication, division, modulus
+ - addition, subtraction
> >= < <= greater than, greater than or equal, less than, less than or equal
== != equality, non-equality

Operators at the same level of precedence are evaluated left-to-right within the expression with the exception of the exponentiation operator which is evaluated right-to-left. In other words, "7/2*4%3" is equivalent to "((7/2)*4)%3" but "1.2^1.3^1.4^1.5" is equivalent to "1.2^(1.3^(1.4^1.5))".

Parenthesis '(' and ')' can be used to group subexpressions to increase their precedence. For example, "3*2+7" would evaluate to 13.0 but "3*(2+7)" would evaluate to 27.0.

Unlike standard Java, the relational operators return a double type rather than a boolean type. They return 1.0 if the relation is true and 0.0 if the relation is false. This is similar to their behavior in C or C++, i.e., the double value of 0.0 is treated as false and any non-zero value is treated as true.

Functions

The table below lists the available functions (those in bold are exactly equivalent to their namesake in java.lang.Math. Note, by default, arguments to the trig functions are expected to be in radians and the inverse trig functions return their results in radians. That can be changed by using the setDegreeMode() method:

Function Description
abs(x) Returns the absolute value of x, see java.lang.Math.abs
acos(x) Returns the arccosine of x, see java.lang.Math.acos
acosh(x) Returns the hyperbolic arccosine of x, equivalent to log(x + sqrt(x^2 - 1))
and(x, y) Returns 1.0 (true) if x and y are both non-zero (true), otherwise returns 0.0 (false)
asin(x) Returns the arcsine of x, see java.lang.Math.asin
asinh(x) Returns the hyperbolic arcsine of x, equivalent to log(x + sqrt(x^2 + 1))
atan(x) Returns the arctangent of x, see java.lang.Math.atan
atan(y, x) Returns the four-quadrant arctangent, see java.lang.Math.atan2
atan2(y, x) Returns the four-quadrant arctangent, see java.lang.Math.atan2
atanh(x) Returns the hyperbolic arctangent of x, equivalent to 0.5*log((1 + x) / (1 - x))
cbrt(x) Returns the cube root of x, see java.lang.Math.cbrt
ceil(x) Returns x rounded up to the nearest integer, see java.lang.Math.ceil
comb(m, n) Number of combinations of m items taken n at a time without replacement
cos(x) Returns the cosine of x, see java.lang.Math.cos
cosh(x) Returns the hyperbolic cosine of x, see java.lang.Math.cosh
e() The base of the natural logarithms, see java.lang.Math.E
exp(x) Returns e raised to the power of x, see java.lang.Math.exp
fact(x) Returns the factorial of x, that is x!
floor(x) Returns x rounded down to the nearest integer, see java.lang.Math.floor
hypot(x, y) Returns sqrt(x^2 + y^2), see java.lang.Math.hypot
if(a, b, c) Returns b if a is non-zero (true), otherwise c is returned
log(x) Returns the natural logarithm of x, see java.lang.Math.log
log(b, x) Returns the base b logarithm of x, equivalent to log(x)/log(b)
log2(x) Returns the base 2 logarithm of x
log10(x) Returns the base 10 logarithm of x, see java.lang.Math.log10
max(x, y) Returns the more positive of x and y, see java.lang.Math.max
min(x, y) Returns the more negative of x and y, see java.lang.Math.min
not(x) Returns 0.0 if x is non-zero otherwise returns 1.0
or(x, y) Returns 1.0 (true) if either x or y or both are non-zero (true), otherwise returns 0.0 (false)
perm(m , n) Number of permutations of m items taken n at a time without replacement
pi() The ratio of a circle's circumference to its diameter, see java.lang.Math.PI
pow(x, y) Returns x to the power of y (same as x^y), see java.lang.Math.pow
round(x) Returns x rounded to the nearest integer, see java.lang.Math.round
signum(x) Returns -1.0 if x is less than zero, +1.0 if x is greater than zero, or 0.0 is x is equal to zero, see java.lang.Math.signum
sin(x) Returns the sine of x, see java.lang.Math.sin
sinh(x) Returns the hyperbolic sine of x, see java.lang.Math.sinh
sqrt(x) Returns the square root of x, see java.lang.Math.sqrt
tan(x) Returns the tangent of x, see java.lang.Math.tan
tanh(x) Returns the hyperbolic tangent of x, see java.lang.Math.tanh
toDegrees(x) Returns x radians converted to degrees, see java.lang.Math.toDegrees
toRadians(x) Returns x degrees converted to radians, see java.lang.Math.toRadians
xor(x, y) Returns 1.0 (true) if either x or y but not both are non-zero (true), otherwise returns 0.0 (false)
Clone this wiki locally