在C#中解决动态计算表达式的问题(如字符串"Sin(1)+Cos(2)",执行并得出结果)
来源:互联网 发布:javascript对象构造器 编辑:程序博客网 时间:2024/05/29 02:24
前一阵公司老总要求我去重构一个同事的程序,里面有各种计算公式,如下图
这个公式的算法是这样
0.058419 + 0.084612 * (log10(第二个文本框的值 / 第一个文本框的值)) + 0.3464 * 第三个文本框的值 + 0.00387 * 第四个文本框的值另一个公式如下图
公式是这样
0.135 + 0.165 * log10(第一个文本框的值/第二个文本框的值)
这两个公式用的是同一窗体,只是加载窗体的时候使用不同的公式而已,所以界面显示的文本框数量,和一些说明文字不一样.
每个公式需要的参数个数不一同,公式算法不一样
我脑海里第一个闪现的做法就是把这些信息整合进一个XML里面进行配置,把计算的公式放进XML里面,呵呵,但是这样仍然解决不了我的问题
现在的公式成了字符串了,而不是程序里面的变量.
由此我想到几种解决方案,它们都属于动态编译,我找到一本英文资料,专门讲C#的元编程<<Manning Metaprogramming in NET 2013>>
这本书提到几种动态编译的方法
1.CodeDom
2.Refection.Emit
3.Lambda表达式树
4.DLR
4个我都看了一下,做了以下总结跟实践
方法1非常好,可以动态编译C#的代码,比如在一个文件框里写MessageBox.Show(......)然后读取文本框里的代码执行,就可以弹出一个文本框,如下图
由此我找到两个来自CodeProject的程序
http://www.codeproject.com/Articles/11939/Evaluate-C-Code-Eval-Function
http://www.codeproject.com/Articles/18004/Net-Expression-Evaluator-using-DynamicMethod
这两个例子都非常好,尤其是第一个例子,演示了怎么执行一段字符串写的代码,以及外部的代码怎么跟字符串写的代码交互,但是要完成我的需要,要写的代码不少!
方法2是操作IL中间语言,我看了一下它的生成代码方式,有一定的灵活度,但要达到我这个程序的要求是太难,太烦,太麻烦!
方法3其生成代码的过程跟方法2比较像,但要轻量级一些,没那么繁琐,它主要是为了动态的生成一个Lambda表达式,但跟方法2一样,不太方便
方法4DLR与动态语言交互,目前.net已经很好的支持了两种脚本语言,Python和Ruby!看了一下Python的语法,感觉比较"轻便"!于是我把公式的计算翻译成Python代码并放入XML文件中,如下
<FormulaInfo MethodSmartPart = "EmpiricalCyq" FormulaName="陈元千相关经验公式" ParameterNameGroup = "地层原油粘度μo(mPa.s)|平均空气渗透率K(mD)|有效孔隙度φ(f)|井网密度S(口/km²)" ParameterRange = "0.5-154.0|4.8-8900.0|0.15-0.33|3.1-28.3" ValidParameter = "0.5-154.0|4.8-8900.0|0.15-0.33|3.1-28.3" Image = "陈元千相关经验公式" Code="def cal(): return 0.058419 + 0.084612 * (log10(float(ArrayCan[1].Text) / float(ArrayCan[0].Text))) + 0.3464 * float(ArrayCan[2].Text) + 0.00387 * float(ArrayCan[3].Text)" />具体做法,我在我的另一篇文章里面有
http://blog.csdn.net/lee576/article/details/18734253
关于IronPython的资料还有一篇写的比较好:
C# 4.0 动态调用 IronPython
http://blog.csdn.net/goldworm2012/article/details/7621632
这个工作做完以后,我感觉方法1还是不错的,但是跟方法4相比,它稍微"重"了一点,但是在执行其它任务时,它是最好的(比如执行一段由字符串写的代码),方法4用来做动态解析计算的时候最合适,代码量少,清晰,并且Python在做科学计算方面比C#要强
- 在C#中解决动态计算表达式的问题(如字符串"Sin(1)+Cos(2)",执行并得出结果)
- C#中另类自定义公式计算 字符串转换为计算公式,并得出计算结果
- 在C#中执行dos命令并返回结果字符串
- 关于OPENGL 圆圈计算弧度的问题 (R*cos(PI * 2 / n*i), R* sin(PI * 2 / n*i));
- sin cos tan在前端的应用
- Ubuntu下使用make编译c文件,不能调用sin cos 等函数问题的解决
- 第13周报告2:定义自定义函数,计算sin和cos的近似值
- 第13周报告2 计算sin和cos的近似值
- C中关于sin(),cos(),pow()函数使用的一个问题
- pb中使用字符串表达式计算结果
- 将某个指定的字符串表达式转换为算术表达式并计算其结果
- 【C】C语言中sin和cos的用法
- 在python中执行shell命令,并以字符串形式返回命令执行结果
- sin和cos的爱恋
- 输出sin,cos的值
- sin与cos的求法
- cos和sin的使用
- 用sin 和cos 的泰勒展开式编程序,求出sin( π/2)、sin(56°)、cos(87°)、cos( π/3)
- Android开发规范
- Smack类库详细介绍
- Android Launcher如何去掉进入应用时的动画效果?
- Socket函数说明
- POJ-3050-Hopscotch
- 在C#中解决动态计算表达式的问题(如字符串"Sin(1)+Cos(2)",执行并得出结果)
- 常用的英语缩写含义
- OJ_1077 最大序列和
- 动态实时跟踪你的java程序
- android repo中manifest.xml的详解
- java学习笔记——基础知识
- 机房综合布线资源管理系统功能介绍
- 定时任务轮询(spring Task)
- 使用异步 I/O 大大提高应用程序的性能