seehttp://www.codeproject.com/dotnet/evaluator.asphttp://www.codeproject.com/csharp/matheval.asp
解决方案 »
- winfrom怎么换窗体的背景?
- 如何在程序中添加动画?
- 求教,在线等~~~ C# winform
- c# 是否可以以panel作为画布?(Graphics)
- 关于C#引用新建文件夹问题如何解决
- 请问如何得到当前日期的下一个星期一?
- 从MSSQL中读出图片并加上文字水印保存到文件夹应该怎么做?在线等,急!!!分不够加...
- 最近用C#编写的QQ游戏对对碰的外挂程序,欢迎指正
- 关于写入的问题啊~~求救啊
- dataset修改数据库时报错:当传递具有新行的DataRow集合时,更新要求有效的 insertCommand。
- 用DataGrid编辑数据时,创建RadioButton对象时,转换无效,请高手指教!三球!!
- 谁有省,市,县级的数据库,高分相送
2. Compile that function into memory
3. Run the function with given x and y
4. Do something with result z value
To do that in a couple of minutes we would need a class with virtual method:namespace MathEval
{
public class MyClassBase
{
public MyClassBase()
{
}
public virtual double eval(double x,double y)
{
return 0.0;
}
}
}all we need more is a parser/evaluator class which would compile function body into assembly (created in memory) and calculate function result:
using System;
using System.Reflection;
using System.Windows.Forms;
namespace MathEval
{
public class MathExpressionParser
{
MyClassBase myobj = null;
public MathExpressionParser()
{
}
public bool init(string expr)
{
Microsoft.CSharp.CSharpCodeProvider cp
= new Microsoft.CSharp.CSharpCodeProvider();
System.CodeDom.Compiler.ICodeCompiler ic = cp.CreateCompiler();
System.CodeDom.Compiler.CompilerParameters cpar
= new System.CodeDom.Compiler.CompilerParameters();
cpar.GenerateInMemory = true;
cpar.GenerateExecutable = false;
cpar.ReferencedAssemblies.Add("system.dll");
cpar.ReferencedAssemblies.Add("matheval.exe");
string src = "using System;"+
"class myclass:MathEval.MyClassBase" +
"{"+
"public myclass(){}"+
"public override double eval(double x,double y)"+
"{"+
"return "+ expr +";"+
"}"+
"}";
System.CodeDom.Compiler.CompilerResults cr
= ic.CompileAssemblyFromSource(cpar,src);
foreach (System.CodeDom.Compiler.CompilerError ce in cr.Errors)
MessageBox.Show(ce.ErrorText); if (cr.Errors.Count == 0 && cr.CompiledAssembly != null)
{
Type ObjType = cr.CompiledAssembly.GetType("myclass");
try
{
if (ObjType != null)
{
myobj = (MyClassBase)Activator.CreateInstance(ObjType);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return true;
}
else
return false;
}
public double eval(double x,double y)
{
double val = 0.0;
if (myobj != null)
{
val = myobj.eval(x,y);
}
return val;
}
}
}Take a look at the init() method. All we need it to do is to create an assembly(in memory) with a class "myclass" derived from MyBaseClass. Note that "eval" method contains the formula given by the user at runtime. Also note that cpar.ReferencedAssemblies.Add("matheval.exe"); defines a reference to the application currently being created.
Then we can call myclass.eval method as many times as we want to:
MathExpressionParser mp = new MathExpressionParser();
mp.init("Math.Sin(x)*y");
for(int i=0;i<1000000;i++)
{
mp.eval((double)i,(double)i);
}Compiled code is of course much faster than any other solution used to parse and evaluate expressions.A few things to do: * Let the user input formulas as "xy*sin(x+y)" or "x^2+y^2" and convert them to c# "x*y*Math.Sin(x+y)" "x*x + y*y" etc...
* Do some error checking/handling other than compiler errors.
* Freeing and recreating the in-memory-assembly with another formula.
* Enjoy the code :)PS: special thanks to AcidRain for some ideas :)
Vlad Tepes Click here to view Vlad Tepes's online profile.Other popular articles: * I/O Ports Uncensored Part 2 - Controlling LCDs (Liquid Crystal Displays) and VFDs (Vacuum Fluorescent Displays) with Parallel Port
Controlling LCDs (Liquid Crystal Displays) and VFDs (Vacuum Fluorescent Displays) with Parallel Port
* Using generics for calculations
Performing calculations with generic types is not as easy it seems. This article shows how to do it.
* Reversi in C#
The game of Reversi in C#.
* Valil.Chess
A chess game written using Visual C# 2005 Express Edition Beta
[Top] Sign in to vote for this article: PoorExcellent Premium Sponsor
using System;
using System.Reflection;
using System.Windows.Forms;
namespace MathEval
{
public class MathExpressionParser
{
MyClassBase myobj = null;
public MathExpressionParser()
{
}
public bool init(string expr)
{
Microsoft.CSharp.CSharpCodeProvider cp
= new Microsoft.CSharp.CSharpCodeProvider();
System.CodeDom.Compiler.ICodeCompiler ic = cp.CreateCompiler();
System.CodeDom.Compiler.CompilerParameters cpar
= new System.CodeDom.Compiler.CompilerParameters();
cpar.GenerateInMemory = true;
cpar.GenerateExecutable = false;
cpar.ReferencedAssemblies.Add("system.dll");
cpar.ReferencedAssemblies.Add("matheval.exe");
string src = "using System;"+
"class myclass:MathEval.MyClassBase" +
"{"+
"public myclass(){}"+
"public override double eval(double x,double y)"+
"{"+
"return "+ expr +";"+
"}"+
"}";
System.CodeDom.Compiler.CompilerResults cr
= ic.CompileAssemblyFromSource(cpar,src);
foreach (System.CodeDom.Compiler.CompilerError ce in cr.Errors)
MessageBox.Show(ce.ErrorText); if (cr.Errors.Count == 0 && cr.CompiledAssembly != null)
{
Type ObjType = cr.CompiledAssembly.GetType("myclass");
try
{
if (ObjType != null)
{
myobj = (MyClassBase)Activator.CreateInstance(ObjType);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return true;
}
else
return false;
}
public double eval(double x,double y)
{
double val = 0.0;
if (myobj != null)
{
val = myobj.eval(x,y);
}
return val;
}
}
}MathExpressionParser mp = new MathExpressionParser();
mp.init("Math.Sin(x)*y");
for(int i=0;i<1000000;i++)
{
mp.eval((double)i,(double)i);
}