Evaluate the function value
You need function evaluator engine for that (it is not that hard to code) there is no way to evaluate sign only if you want to support +,- operations !!! All my function evaluators works like this:
compile the source text of the function
First create supported functions table (id,num of operands,name,pointer to function) like:
+,-,*,/,sin,cos,....
These will be the building blocks to any supported expression you need to evaluate. Do not forget to code all functions in your code too. Handle brackets (
,)
also as functions (push,pop
). Group your functions by number of operands so +,-
are with 1 and 2 operands (two different functions each !!!).
Now from expression extract:
- variable names
- constant names and values
- number values
Into some kind of table/list:
variables[](id,name,value)
constants[](id,name,value)
numbers [](id, ,value)
And now finally construct compiled function string. My strings are set of two int
's. First is type
(which table to use) and second is id
(index in table).
for example expression:
sign(sqrt(2)-1)
types:
id type
0 function
1 number
2 constant
3 variable
functions:
id name pointer
0 '(' ???
1 ')' ???
2 '+' ???
3 '-' ???
4 '*' ???
5 '/' ???
6 'sqrt' ???
7 'sign' ???
There are no variables or constants. The numbers are:
id value
0 2
1 1
compiled string:
type id
0 7 // sign(1 operand)
0 6 // sqrt(1 operand)
1 0 // 2
0 3 // - (2 operands)
1 1 // 1
After compilation you need to interpret the string and evaluate it's value.
init variables
op1=0`,`op2=0, // set all operands to zero (number depends on supported functions usually 2)
opn=0 // actual operands number
fx=none // actual function (for example none=-1)
fxn=0 // actual function operands number
read first record of compiled string
if it is value (number,constant,variable) set appropriate op?
value with it and increment operand counter opn++
.
if it is function set fx,fxn
code with it
if opn == fxn
You reached needed operand count so execute function fx
and init next function
op1=fxtab[fx].pointer(op1,op2,...)
fx=none,fxn=1
opn=1 (some spec functions can return more operands, then set op1,op2,.. opn=...)
if not end of string goto #2 but with next string record
at the end op1
should hold your output value
some example functions (C++ implementation):
double sign(double op1)
{
if (op1>0.0) return +1.0;
if (op1<0.0) return -1.0;
return 0.0;
}
double sqrt1(double op1) { return sqrt(op1); }
double plus1(double op1) { return op1; }
double minus1(double op1) { return -op1; }
double plus2(double op1,double op2) { return op1+op2; }
double minus2(double op1,double op2) { return op1-op2; }
[Notes]
You have to handle special cases like function = "";
. Also beware spacing, case sensitivity because any error in compilation invalidates the result.
Speed is not a big issue this is interpreting-evaluation not numerical solution. All operations are called the same times as you would do on the paper.
You should also handle mathematic errors (overflows,invalid operands,NaN
,Inf
...)
I usually group functions with the same number of operands to own type to simplify things
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…