Method to extract values from an expression

42 views
Skip to first unread message

bazt...@gmail.com

unread,
Apr 28, 2016, 5:34:01 PM4/28/16
to Jep Java Users
Hi,
In version 3.4, how might I extract the values from an expression when some of the values may be a negative number?
The context is I'm allowing my users to enter an equation for a linear regression trend; straight line trend.
I want the values for the slope and the intercept, I don't need to evaluate the expression as a line is built from the slope and intercept.

I would like them to be able to enter all forms of the expression:
y = x-2 + 3
y = x4 + 1
y = x-3 - 4
y = x7 - 3
y = x

The 'y = x *' part is filtered out, it's only there for presentation purposes.

Does Jep offer this kind of functionality?

Thanks in advance,
Sebastien

Richard Morris

unread,
May 3, 2016, 7:00:51 AM5/3/16
to Jep Java Users, bazt...@gmail.com
Sebastien,

I think Jep can do this. The page http://www.singularsys.com/jep/doc/html/manipulating.html describes ways of working with the parsed expression.
You should be able to examine the parse tree using methods of the main Node interface


this has methods
      int jjtGetNumChildren()
which get the number of children,
      Node jjtGetChild(int i)
which finds the i-th child of a node, and
    Object getValue() 
which for constant nodes gets the value of that node.

You can use code like 

@Test
public void testSlope() throws JepException {
Jep jep = new Jep();
        OperatorTableI ot = jep.getOperatorTable();

        Node n = jep.parse("x*-3-5");
Node l = n.jjtGetChild(0); // x*-3 
        Node r = n.jjtGetChild(1); // - 5
        Node ll = l.jjtGetChild(0); // x
        Node lr = l.jjtGetChild(1); // -(3)

        double slope=0.0;
        if(lr.getOperator() != null && lr.getOperator().equals(ot.getUMinus())) {
            Node lrl = lr.jjtGetChild(0); // 3
            slope = -((Double) lrl.getValue());
        } else {
            slope = (Double) lr.getValue();
        }
        
        double intercept = 0.0;
        if( n.getOperator().equals(ot.getAdd())) {
            intercept = (Double) r.getValue();
        } else if( n.getOperator().equals(ot.getSubtract())) {
            intercept = -(Double) r.getValue();
        }
               
        assertEquals("x",ll.getName());
        assertEquals(-3.0,slope,1e-6);
        assertEquals(-5.0,intercept,1e-6);    
}


Note that the way the parser works the expression "x * -3" is parsed as "x * -(3)", where -() is the unitary minus operator. If you don't know in the input is going to 
be "x*3-5" or "x*-3-5" you will need to test if the rhs of the left node is a unitary minus operator. You can do this with

if(lr.getOperator() != null && lr.getOperator().equals(ot.getUMinus())) { ... }

testing to see if the node is an operator, and checking that the operator is the Uminus operator. A slightly simpler way of doing this is

if(ot.getUMinus().equals(lr.getOperator())) { ... }

The same needs to be done with the intercept as you need to check if the operator is an addition or subtraction.

Depending on how well you know the input you may need to do additional test to look for alternative ways of inputting the equation say "-3*x-5".

Richard

bazt...@gmail.com

unread,
May 3, 2016, 4:50:52 PM5/3/16
to Jep Java Users, bazt...@gmail.com
Hi Richard,
Thanks for the example.

I pretty much managed it in the same way, however not using an OperatorTable. I think that using the OperatorTable to use for comparing what the operator, if any, is would be a cleaner way to implement.

How I did it:

slope
= getSlopeFormExpression(jep.getLastRootNode());
intercept
= getInterceptFromExpression(jep.getLastRootNode());


String getSlopeFormExpression(Node node) {
 
return processNodeForValueAsString(node.jjtGetChild(0));
}


String getInterceptFromExpression(Node node) {
 
String results;
 results
= processNodeForValueAsString(node.jjtGetChild(1));

 
if(jep.getLastRootNode().getOperator().getSymbol().equals("+")) {
 
return results;
 
} else {
 
if(!results.startsWith("-")) {
 results
= "-" + results;
 
} else {
 
int pos = results.indexOf("-");
 results
= results.substring(pos+1);
 
}
 
}

 
return results;
}

String processNodeForValueAsString(Node node) {
if(node.getOperator() != null) {
 
return node.getOperator().getSymbol() + node.jjtGetChild(0).getValue().toString();
 
} else {
 
return node.getValue().toString();
 
}
}



Reply all
Reply to author
Forward
0 new messages