| Feature | Package (JavaDoc) |
| Assignment | org.nfunk.jep.* |
| New Syntax for parsing and evaluation (allows several expressions to be used simultaneously) | org.nfunk.jep.* |
| New Functions | org.nfunk.jep.* |
| Changes to ways variables are implemented. | org.nfunk.jep.* |
| Observers can detect changes in variables and new variable creation. | org.nfunk.jep.* |
Assignment allows the values of variables to be set by using the = operator in equations so it is possible to do something like x=3 then y=x^2 and y will have the value 9. Assignment can be used with the standard JEP package, there is no need to use any of the packages in the org.lsmp.djep tree. To switch on assignment facilities the setAllowAssignment method of the main JEP object should be called.
// standard initialisation
JEP j = new JEP();
j.addStandardConstants();
j.addStandardFunctions();
j.addComplex();
j.setAllowUndeclared(true);
j.setImplicitMul(true);
// switch assignment facilities on
j.setAllowAssignment(true);
// parse assignment equations
j.parseExpression("x=3");
// evaluate it - no need to save the value returned (unless you want to)
j.getValueAsObject();
// parse a second equation
j.parseExpression("y=2");
j.getValueAsObject();
// an equation involving above variables
j.parseExpression("x^y");
Object val3 = j.getValueAsObject();
System.out.println("Value is "+val3);
A couple of utility functions have been added to the make it easier to work with a set of related equations. These are:
public Node parse(String expression) throws ParseExceptionwhich parse and evaluate the expression. These can be used like
public Object evaluate(Node node) throws Exception
try
{
// Alternative syntax
Node node1 = j.parse("z=i*pi");
j.evaluate(node1);
Node node2 = j.parse("exp(z)");
Object val2 = j.evaluate(node2);
System.out.println("Value: "+val2);
}
catch(ParseException e) {
System.out.println("Error with parsing");
}
catch(Exception e) {
System.out.println("Error with evaluation");
}
Hence its a bit easier to keep track of a number of equations. Note that using this syntax Exceptions need to be caught and the getTopNode() method will not return meaningful results.
The value of a variable can be set and queried using the setVarValue and getVarVal methods of the jep instance. A further method getVar returns an object representing the variable.
JEP j = new JEP();
try {
Node node = j.parse("z=x^y");
j.setVarValue("x",new Double(2));
j.setVarValue("y",new Double(3));
j.evaluate(node);
System.out.println(j.getVarValue("z")); // prints 8
} catch .....
The SymbolTable class now stores objects representing variables rather than
just their values and the get
and put
methods of this class are deprecated. This results in a slight speed up during
evaluation.
Variables can be constants which cannot have their values changed. To add a new constant use addConstant to add a mutable variable use addVariable.
Both SymbolTable and Variable implement the Observer/Observable pattern. This allows objects to be informed whenever a new variable is created or when its value has been changed. An example of use is
public class MyObserver implements Observer
{
public void initialise()
{
SymbolTable st = j.getSymbolTable();
st.addObserver(this);
st.addObserverToExistingVariables(this);
}
public void update(Observable arg0, Object arg1)
{
if(arg0 instanceof Variable)
println("Var changed: "+arg0);
else if(arg0 instanceof SymbolTable.StObservable)
{
println("New var: "+arg1);
// This line is vital to ensure that
// any new variable created will be observed.
((Variable) arg1).addObserver(this);
}
}
}