四种Eval测试结果:不要用CodeDom做大批量的表达式四则运算

原创 2002年12月16日 09:34:00

有时候需要表达式运算,如
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的话)
和第三种(代码简单,功能更多)

C语言实现整数四则运算表达式的计算

一、问题重述 【问题描述】 从标准输入中读入一个整数算术运算表达式,如5 - 1 * 2 * 3 + 12 / 2 / 2  = 。计算表达式结果,并输出。 要求: 1、表达式运算符只有+、-、*、/...
  • dannis_bh
  • dannis_bh
  • 2016年03月29日 02:24
  • 6279

在Java中计算四则运算表达式字符串的值

原文链接:http://zywang.iteye.com/blog/462797 在项目中有个需求,需要动态的计算一个四则运算表达式的结果,在JS中做这个非常方便,用eval表达...
  • zhangbest2009
  • zhangbest2009
  • 2015年05月13日 17:34
  • 2639

栈的应用:四则运算表达式求值

栈的一个应用就是四则运算表达式的求值,
  • lub0807
  • lub0807
  • 2014年07月17日 20:08
  • 1978

js 正则表达式/g对exec()测试结果的影响

遇到一个bug,代码的执行完全不在期望之内。 我写了一段这样的代码,实现的功能,就想实现一个简单的jquery选择器功能。function $(selector){ var ID_R...
  • zd10101501
  • zd10101501
  • 2016年04月20日 22:03
  • 654

ACCESS数据库大数据量分页的几种方法比较及测试结果分析

  • 2010年07月25日 10:55
  • 88KB
  • 下载

排序算法大数据量测试结果

MergeSorter排序40000个数1次所用平均时间为:19.0011 毫秒  MergeSorter排序60000个数1次所用平均时间为:26.0015 毫秒  MergeSorter排序800...
  • xunzaosiyecao
  • xunzaosiyecao
  • 2014年01月08日 09:48
  • 1611

jmeter和loadrunner测试结果差异大-web页面静态资源下载

最近有朋友性能测试时遇到Jmeter和Loadrunner测试的结果差异很大,对结果很纠结。笔者在与之一同排查的过程中发现很多老司机也总会踩到的坑-web页面静态资源下载. 问题:jmeter和l...
  • meitingbee
  • meitingbee
  • 2016年12月28日 18:14
  • 2162

UV镜还是保护镜?差异很大啊!(附14款镜片测试结果)

http://www.360doc.cn/article/8263899_209780489.html 我之前只知道数码相机对紫外线不是很敏感(这个结论应该没有问题吧)所以我选择镜片的时候一直只...
  • hshl1214
  • hshl1214
  • 2015年06月14日 09:31
  • 11568

深入理解loadrunner的测试结果

  • 2008年05月06日 13:00
  • 107KB
  • 下载

IB(InfiniBand网卡性能测试结果)

  • 2012年05月15日 23:15
  • 597KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:四种Eval测试结果:不要用CodeDom做大批量的表达式四则运算
举报原因:
原因补充:

(最多只允许输入30个字)