خوب من این نمونه اولیه را 2 سال پیش نوشته بودم یادش بخیر هیچ وقت به درد من نخورد.
using System;
using System.Collections;
using System.Collections.Generic;
namespace Arman_Math_Interpreter
{
#region struct's
public struct VarRec
{
public string name;
public double value;
}
public enum stmtype
{
mfunction,
mnumber,
mparantez
}
public enum optype
{
nul,
plus,
neg,
mul,
div,
pow
}
public struct mathnode
{
public string name;
public stmtype kind;
public double value;
public optype nx_op;
public bool neg;
public int nx1;
public int nx2;
}
#endregion
public class Arman_Math_Interpreter
{
#region field's
public int err_code;
public bool err;
public double value;
private string fstr;
private List<VarRec> fvarlist=new List<VarRec>();
private List<mathnode> fstmt = new List<mathnode>();
private mathnode fs;
#endregion
#region property's
public string str
{
get
{
return fstr;
}
set
{
fstr = value;
}
}
#endregion
public Arman_Math_Interpreter(string value)
{
fstr = value;
err = false;
addvar("pi",Math.PI);
}
#region variable' manager
public bool addvar(string name,double value)
{
VarRec mvar;
if (search(name,out mvar))
return false;
mvar.name=name;
mvar.value=value;
fvarlist.Add(mvar);
return true;
}
public bool search(string name,out VarRec mvar)
{
foreach (VarRec mvar2 in fvarlist)
{
if (mvar2.name == name)
{
mvar = mvar2;
return true;
}
}
mvar =new VarRec();
return false;
}
public double getvar(string name)
{
VarRec mvar;
if(search(name,out mvar))
return mvar.value;
return 0.0;
}
public bool setvar(string name, double value)
{
VarRec mvar;// = search(name);
if (search(name,out mvar))
return false;
mvar.value = value;
return true;
}
public bool delvar(string name)
{
VarRec mvar;// = search(name);
if (search(name,out mvar))
return false;
fvarlist.Remove(mvar);
return true;
}
public void clearvarlist()
{
fvarlist.Clear();
}
#endregion
#region statemment manager
public void initmathnode(ref mathnode m)
{
m.kind=stmtype.mnumber;
m.name="";
m.neg=false;
m.nx_op=optype.nul;
m.value=0.0;
m.nx1 = -1;
m.nx2 = -1;
}
private bool readparantez(ref mathnode m,ref int mpos)
{
mathnode ptr1, ptr2;
int index = -1;
int index2 = -1;
string tstr = "";
bool f = true;
bool fneg = false;
char[] ops = { '+', '-', '(', ')', '*', '/', '^' };
//
do
{
mpos++;
bool ch=false;
foreach(char c in ops)
ch=ch || fstr[mpos]==c;
if(ch)
{
if(tstr=="" && (fstr[mpos]!='('))
{
//
if(fstr[mpos]=='-'){
fneg=!fneg;
continue;
}
//
if (fstr[mpos]=='+')
continue;
err=true;
return false;
}
//
ptr1=new mathnode();
initmathnode(ref ptr1);
ptr1.name=tstr;
ptr1.neg=fneg;
fstmt.Add(ptr1);
index = fstmt.IndexOf(ptr1);
if (f)
{
m.nx2 = index;
f = false;
}
else
{
ptr2 = (mathnode)fstmt[index2];
ptr2.nx1 = index;
fstmt[index2] = ptr2;
}
ptr2=ptr1;
index2 = index;
if(fstr[mpos]=='(')
{
if(tstr=="")
ptr1.kind=stmtype.mparantez;
else
ptr1.kind=stmtype.mfunction;
readparantez(ref ptr1,ref mpos);
ptr1.name=tstr.ToLower();
mpos++;//move after )
}
//
switch(fstr[mpos]){
case '+' :
ptr1.nx_op=optype.plus; break;
case '-' :
ptr1.nx_op=optype.neg; break;
case '*':
ptr1.nx_op=optype.mul; break;
case '/':
ptr1.nx_op=optype.div; break;
case '^':
ptr1.nx_op=optype.pow; break;
}
fstmt[index] = ptr1;
tstr="";
continue;
}
if(fstr[mpos]!=')')
tstr=tstr+fstr[mpos];
}
while (fstr[mpos]!=')'|| (mpos>=fstr.Length));
return true;
}
public bool createtree()
{
int mpos = -1;//first of string
if (fstr.Length == 0) return true;
if (fstmt.Count > 0)
fstmt.Clear();
mathnode first = new mathnode();
initmathnode(ref first);
first.kind = stmtype.mparantez;
fstmt.Add(first);
fstr = fstr + ')';
readparantez(ref first,ref mpos);
if (err)
{
fstmt.Clear();
return false;
}
fs = first;
return true;
}
private double solveitem(ref mathnode ptr)
{
double tmpval, val2;
VarRec pvar;
mathnode m1,m2;
tmpval = 0.0;
if (ptr.nx1 != -1)
m1 = (mathnode)fstmt[ptr.nx1];
else
m1 = new mathnode();
if (ptr.nx2 != -1)
m2 = (mathnode)fstmt[ptr.nx2];
else
m2 = new mathnode();
if (err) return 0;
//
if (ptr.kind == stmtype.mnumber)
{
if (!double.TryParse(ptr.name, out tmpval))
{
if (!search(ptr.name,out pvar))
{
err = true;
return tmpval;
}
tmpval = getvar(ptr.name);
}
//
if (ptr.neg)
tmpval *= -1;
if (ptr.nx1 != -1)
{
switch (ptr.nx_op)
{
case optype.plus:
tmpval += solveitem(ref m1);
break;
case optype.neg:
tmpval -= solveitem(ref m1);
break;
case optype.mul:
tmpval *= solveitem(ref m1);
break;
case optype.div:
{
val2 = solveitem(ref m1);
if (tmpval == 0)
{
err = true;
return tmpval;
}
tmpval /= solveitem(ref m1);
}
break;
case optype.pow:
tmpval = Math.Pow(tmpval, solveitem(ref m1));
break;
}
}
ptr.value = tmpval;
return tmpval;
}//end of number's
//function's
if (ptr.kind == stmtype.mfunction)
{
if (ptr.nx2 == -1)
{
err = true;
return tmpval;
}
tmpval = solveitem(ref m2);
//use math function's
if (ptr.name == "sin")
tmpval = Math.Sin(tmpval);
else if (ptr.name == "cos")
tmpval = Math.Cos(tmpval);
else if (ptr.name == "tan")
tmpval = Math.Tan(tmpval);
else if (ptr.name == "cot")
tmpval = 1/Math.Tan(tmpval);
else if (ptr.name == "abs")
tmpval = Math.Abs(tmpval);
else if (ptr.name == "sqrt")
tmpval = Math.Sqrt(tmpval);
else if (ptr.name == "trunc")
tmpval = Math.Truncate(tmpval);
else if (ptr.name == "log10")
tmpval = Math.Log10(tmpval);
else if (ptr.name == "log2")
tmpval = Math.Log(tmpval,2);
else if (ptr.name == "exp")
tmpval = Math.Exp(tmpval);
else if (ptr.name == "sinh")
tmpval = Math.Sinh(tmpval);
else if (ptr.name == "cosh")
tmpval = Math.Cosh(tmpval);
else if (ptr.name == "tanh")
tmpval = Math.Tanh(tmpval);
else if (ptr.name == "coth")
tmpval = 1/Math.Tanh (tmpval);
//end of usage
//
if (ptr.neg)
tmpval *= -1;
if (ptr.nx1 != -1)
{
switch (ptr.nx_op)
{
case optype.plus:
tmpval += solveitem(ref m1);
break;
case optype.neg:
tmpval -= solveitem(ref m1);
break;
case optype.mul:
tmpval *= solveitem(ref m1);
break;
case optype.div:
{
val2 = solveitem(ref m1);
if (tmpval == 0)
{
err = true;
return tmpval;
}
tmpval /= solveitem(ref m1);
}
break;
case optype.pow:
tmpval = Math.Pow(tmpval, solveitem(ref m1));
break;
}
}
ptr.value = tmpval;
return tmpval;
}//end of function's
//parantez
if (ptr.kind == stmtype.mparantez)
{
if (ptr.nx2 == -1)
{
err = true;
return tmpval;
}
tmpval = solveitem(ref m2);
//
if (ptr.neg)
tmpval *= -1;
if (ptr.nx1 != -1)
{
switch (ptr.nx_op)
{
case optype.plus:
tmpval += solveitem(ref m1);
break;
case optype.neg:
tmpval -= solveitem(ref m1);
break;
case optype.mul:
tmpval *= solveitem(ref m1);
break;
case optype.div:
{
val2 = solveitem(ref m1);
if (tmpval == 0)
{
err = true;
return tmpval;
}
tmpval /= solveitem(ref m1);
}
break;
case optype.pow:
tmpval = Math.Pow(tmpval, solveitem(ref m1));
break;
}
}
ptr.value = tmpval;
return tmpval;
}//end of parantez
return 0.0;
}
public bool solve()
{
err = false;
value = 0;
if (fstmt.Count > 0)
try
{
value = solveitem(ref fs);
return true;
}
catch { }
return false;
}
public void cleartree()
{
fstmt.Clear();
}
#endregion
}
}