Frequently Asked Questions

Why is Jep giving inaccurate results?

You will notice that when you evaluate something as simple as "8 - 7.9" the result will be 0.09999999999999964 rather than 0.1. These inaccuracies are the result of floating point arithmetic. Internally, Jep uses the double type to represent numbers by default. Unfortunately, even for trivial calculations such as "8 - 7.9" the calculation can not be performed accurately.

You will notice the same if you run the following code.

double a=8, b=7.9;
System.out.println("a-b = " + (a-b));
//prints a-b = 0.09999999999999964

So this is not a Jep flaw, just a limitation of using floating point numbers. Although floating point numbers are accurate enough for many applications, these types of errors should not be ignored in applications where accuracy is critical.

By using System.out.printf results from Jep can be displayed to a given number of decimal places. For example

jep.parse("8-7.9");
double res = jep.evaluateD();
System.out.printf("%.3f",res);

Which will print the result to three decimal places: 0.100. See java.util.Formatter for details on formatting output. The java.text.NumberFormat class can also be used to format results.

Jep has a round function, which can round arguments to a given number of decimal places. round(8-7.9,1) will round results to one decimal place.

To avoid this problem, use the BigDecimal components as described in the BigDecimal section. They allow you to perform calculations with arbitrary accuracy unlike floating point arithmetic.

How should I handle NULL values?

If Jep is throwing an exception "EvaluationException: Could not evaluate XXX : no value set for the variable." during evaluation, then you are running in to issues with null values.

It is important to note that by default variables whose values have not been set by either

jep.addVariable(name,value);

or by parsing an expression like

XXX = 123.456;

will remain initialized to null. So when you attempt to evaluate and expression with a null variable, the evaluator will by default throw an exception when the null value is encountered.

There are a several of ways around this:

  1. Depending on the evaluator you are using, you can turn off the check for null values with
    ((StandardEvaluator)jep.getEvaluator()).setTrapNullValues(false);
    or
    ((FastEvaluator)jep.getEvaluator()).setTrapNullValues(false);
    in which case null values will be passed to the individual functions.
  2. You can change the default value used for unassigned variables with
    jep.getVariableFactory().setDefaultValue(Double.valueOf(0.0));
  3. A more advanced treatment of null values would be to create a type to represent genuine null values, create a constant NULL to recognise NULL in the parser and explicitly set NULL variables.
      Object MyNULL = new Object(); // create a null value
      jep.addConstant("NULL",MyNULL); // define a constant in the parser
      jep.addVariable("x",MyNULL); // add a variable with the NULL value
      jep.parse("y=NULL"); // expression assigning a variable to NULL
      jep.parse("x==NULL"); // Compare a variable to the NULL value
      
  4. Since version 3.4, the src.com.singularsys.jep.misc.nullwrapper package allows for null values to be treated like NULL in a database. Any function or operator with null as an argument will return null. For instance null+5 will be null. The package takes existing operators and functions and adds a wrapper class which will test if a null value is input; if so, null is returned, otherwise the original function is used. The NullWrappingOperatorTable and NullWrapperFunctionTable wrap all the existing operators and functions. To set this up use
    jep.setComponent(new NullWrappingOperatorTable(
                      (OperatorTable2) jep.getOperatorTable(),true));
    jep.setComponent(new NullWrapperFunctionTable(jep.getFunctionTable()));
    jep.setComponent(new StandardConfigurableParser());
    ((FastEvaluator) jep.getEvaluator()).setTrapNullValues(false);
      

    The operator table also adds an additional operator, the null safe equals <=>, and the StandardConfigurableParser is needed to add this to the parser.

Why am I getting an EvaluationException?

There can be several reasons for EvaluationExceptions to be thrown. Of course it is best to look at the message in the exception for more details.

If you are seeing

com.singularsys.jep.EvaluationException: Could not evaluate XXX : no
    value set for the variable.

then refer to "How should I handle NULL values?" in this FAQ.

Other evaluation exceptions are typically due functions or operators not being compatible with the data types passed in. Since Jep only checks data types during evaluation, you will not see these issues while parsing an expression.

How can I allow variable names with a dot in them?

To do this, you need to use the Configurable Parser which allows great control over the input syntax. The following code sets up the parser with the standard options but using identifiers with a dot in them as well by using the factory method com.singularsys.jep.configurableparser.matchers.IdentifierTokenMatcher.dottedIndetifierMatcher(). The final step in setting up is to remove the dot-product "." operator to prevent any ambiguity.

ConfigurableParser cp = new ConfigurableParser();
cp.addHashComments();
cp.addSlashComments();
cp.addDoubleQuoteStrings();
cp.addWhiteSpace();
cp.addExponentNumbers();
cp.addOperatorTokenMatcher();
cp.addSymbols("(",")","[","]",",");
cp.setImplicitMultiplicationSymbols("(","[");

// Sets it up for identifiers with dots in them.
cp.addTokenMatcher(IdentifierTokenMatcher.dottedIndetifierMatcher());

cp.addSemiColonTerminator();
cp.addWhiteSpaceCommentFilter();
cp.addBracketMatcher("(",")");
cp.addFunctionMatcher("(",")",",");
cp.addListMatcher("[","]",",");
cp.addArrayAccessMatcher("[","]");

// Construct the Jep instance and set the parser
jep = new Jep(cp);

// Remove the dot operator
OperatorTable2 ot = (OperatorTable2)jep.getOperatorTable();
ot.removeOperator(ot.getDot());
//notify other components of change in operator table
jep.reinitializeComponents();

How can I reduce the size of Jep?

The memory footprint of Jep can be reduced in a number of ways.

For example you could create a Jep instance with no loaded functions with:

Jep jep1 = new Jep(new FunctionTable(), new StandardConfigurableParser()); 
And you can create a Jep instance without parser and without functions with:
Jep jep2 = new Jep(new FunctionTable(), new NullParser());

The com.singularsys.jepexamples.diagnostics.ExamineSizes program gives give a detailed breakdown of memory usage.