首 页 | 新 闻 | 技术中心 | 第二书店 | 《程序员》 | 《开发高手》 | 社 区 | 黄 页 | 人 才
移 动专 题SUNIBM微 软微 创精 华Donews人 邮
我的技术中心 
我的分类 我的文档
全部文章 发表文章
专栏管理 使用说明



 RSS 订阅 
最新文档列表
Windows/.NET
.NET  (rss)    
Visual C++  (rss)    
Delphi  (rss)    
Visual Basic  (rss)    
ASP  (rss)    
JavaScript  (rss)    
Java/Linux
Java  (rss)    
Perl  (rss)    
综合
其他开发语言  (rss)    
文件格式  (rss)    
企业开发
游戏开发  (rss)    
网站制作技术  (rss)    
数据库
数据库开发  (rss)    
软件工程
其他  (rss)    

积极原创作者 
goodboy1881 (13)
wangchinaking (58)
iiprogram (67)
fancyhf (1)
harrymeng (41)
yjz0065 (113)
coofucoo (105)
Drate (69)
lphpc (30)
smallnest (61)
CSDN - 文档中心 - .NET 阅读:3557   评论: 0    参与评论
标题   四种Eval测试结果:不要用CodeDom做大批量的表达式四则运算     选择自 qiushuiwuhen 的 Blog
关键字   秋水无恨 CodeDom Compiler 数据结构 Vsa eval
出处  

有时候需要表达式运算,如
String strExpression="-12 * ( - 2.2 + 7.7 ) - 44 * 2";

网上找的,一般是利用CodeDom,见
http://www.codeproject.com/csharp/runtime_eval.asp

简化为:
 System.CodeDom.Compiler.ICodeCompiler comp = (new Microsoft.CSharp.CSharpCodeProvider().CreateCompiler());
 System.CodeDom.Compiler.CompilerParameters cp = new System.CodeDom.Compiler.CompilerParameters();

object qswhEval2(string Expression){
 StringBuilder code = new StringBuilder();
 code.Append("using System; \n");
 code.Append("namespace ADOGuy { \n");
 code.Append("  public class _Evaluator { \n");
 code.Append("    public object __foo() ");
 code.Append("{ ");
 code.AppendFormat("      return ({0}); ", Expression);
 code.Append("}\n");
 code.Append("} }");
 System.CodeDom.Compiler.CompilerResults cr = comp.CompileAssemblyFromSource(cp, code.ToString());
 System.Reflection.Assembly a = cr.CompiledAssembly;
 object _Compiled = a.CreateInstance("ADOGuy._Evaluator");
 System.Reflection.MethodInfo mi = _Compiled.GetType().GetMethod("__foo");
 return mi.Invoke(_Compiled, null);
}

 
但用起来感觉很慢,毕竟需要实时编译。

于是,就自己照数据结构书上写了一种算法:
string Precede(string p, string q){
 switch(p){
  case "+":
  case "-":return ("*/(".IndexOf(q)!=-1)?"<":">";
  case "*":
  case "/":return (q=="(")?"<":">";
  case "(":return (q==")")?"=":"<";
  case ")":return (q=="(")?"?":">";
  case "#":return (q=="#")?"=":"<";
 }
 return "?";
}
Double Operate(Double a,char o,Double b)
{
   switch(o)
    {
      case '+':return a+b;
      case '-':return a-b;
      case '*':return a*b;
      case '/':return a/b;
    }
    return 0;
}

Object qswhEval1(string Expression){
 /*************(qiushuiwuhen 2002-12-14)****************/
 Stack nArr=new Stack(),oArr=new Stack();
 int j=0;
 Double a=0,b=0;
 string w="";
 char o;
 MatchCollection arr=Regex.Matches(Expression.Replace(" ","")+"#",@"(((?<=(^|\())-)?\d+(\.\d+)?|\D)");
 
 oArr.Push('#');
 w=Convert.ToString(arr[j++]);
 while(!(w=="#"&&Convert.ToString(oArr.Peek())=="#")){
  if("+-*/()#".IndexOf(w)!=-1){
   switch(Precede(oArr.Peek().ToString(),w)){
    case "<":
      oArr.Push(w);
      w=Convert.ToString(arr[j++]);
      break;
    case "=":
      oArr.Pop();
      w=Convert.ToString(arr[j++]);
      break;
    case ">":
      o=Convert.ToChar(oArr.Pop());
      b=Convert.ToDouble(nArr.Pop());
      a=Convert.ToDouble(nArr.Pop());
      nArr.Push(Operate(a,o,b));
      break;
    default:
      return "Error";
      break;
     
   }
  }else{
   nArr.Push(w);
   w=Convert.ToString(arr[j++]);
  }
 }
 return nArr.Pop();
}

还有利用JScript的Eval的两种算法
Microsoft.JScript.Vsa.VsaEngine ve=Microsoft.JScript.Vsa.VsaEngine.CreateEngine();
object qswhEval3(string Expression){
 return Microsoft.JScript.Eval.JScriptEvaluate(Expression,ve);
}

object qswhEval4(string Expression){
 return qswhJs.qswhEval.Eval(Expression);
}

第四种需先建立一js编译为dll,如下代码
import System;

package qswhJs {
  class qswhEval {
    static function Eval(Expression):Object { return eval(Expression); }
  }
}

测试代码如下:
void Page_Load(Object o,EventArgs ea){
 String strExpression="-12 * ( - 2.2 + 7.7 ) - 44 * 2";
 int i=0,c=100;
 DateTime d1,d2;
cp.GenerateExecutable = false;
cp.GenerateInMemory = true;
 
 d1=DateTime.Now;
 for(i=0;i<c;i++)qswhEval1(strExpression);
 d2=DateTime.Now;
 Response.Write("方法一:对表达式分析 "+d2.Subtract(d1)+"<br>");
 
 d1=DateTime.Now;
 for(i=0;i<c;i++)qswhEval2(strExpression);
 d2=DateTime.Now;
 Response.Write("方法二:利用CodeCom  "+d2.Subtract(d1)+"<br>");
 
 d1=DateTime.Now;
 for(i=0;i<c;i++)qswhEval3(strExpression);
 d2=DateTime.Now;
 Response.Write("方法三:利用Jscript+Vsa  "+d2.Subtract(d1)+"<br>");
 
 d1=DateTime.Now;
 for(i=0;i<c;i++)qswhEval4(strExpression);
 d2=DateTime.Now;
 Response.Write("方法四:利用Jsc+Dll  "+d2.Subtract(d1)+"<br>");
}

测试结果:

方法一:对表达式分析 00:00:00.1702448
方法二:利用CodeCom 00:00:23.7942144
方法三:利用Jscript+Vsa 00:00:00.1902736
方法四:利用Jsc+Dll 00:00:00.2403456

在此推荐第一种(如果要纯CSharp的话)
和第三种(代码简单,功能更多)


相关文章
对该文的评论