CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
山寨机中的战斗机! 程序优化工程师到底对IT界有没有贡献
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  .NET技术 >  VB.NET

如何实现把一个字符["a+b*(c-a)*(d*r)"]串转化为公式替换为变量进行计算高手指点

楼主zyb1235(翟)2006-04-03 17:32:32 在 .NET技术 / VB.NET 提问

[{(w-0)*(21-w)}]*(100+[(w-0.5)/0.5]*40)+[{(w-21)*(50-w)}]*[w]*60+[{([w]-51)*(100-w)}]*[w]*55+[[w]-100]*[w]*50    
  标题是一个简单的这时我找的一个公式如何转换并运算。 问题点数:50、回复次数:12Top

1 楼copico(北北)回复于 2006-04-03 17:40:23 得分 0

有点像以前的编译课程设计Top

2 楼someboy53(浪人)回复于 2006-04-03 20:26:14 得分 0

如果不要求速度的话,可以把这段字符当作源代码实时编译,再运行来计算!  
   
  你可以看一下VBCodeProvider   类.Top

3 楼HAVENT(夜雨流星℡)回复于 2006-04-04 08:31:01 得分 0

思索一下Top

4 楼zyb1235(翟)回复于 2006-04-04 10:34:55 得分 0

这段字符是可以由文本框输入存入数据库的编译进去不可能  
  所以还有没有其它办法。特急!Top

5 楼MSTOP(陈建华)回复于 2006-04-04 11:07:43 得分 20

 
  '//======================================  
  '//窗体控钮.  
  '//=======================================  
          Private   Sub   btnEval_Click(ByVal   sender   As   System.Object,   ByVal   e   As   System.EventArgs)   Handles   btnEval.Click  
                  Dim   expr   As   String   =   "[{(w-0)*(21-w)}]*(100+[(w-0.5)/0.5]*40)+[{(w-21)*(50-w)}]*[w]*60+[{([w]-51)*(100-w)}]*[w]*55+[[w]-100]*[w]*50   "  
                  expr   =   Replace(expr,   "{",   "(")  
                  expr   =   Replace(expr,   "}",   ")")  
                  expr   =   Replace(expr,   "[",   "(")  
                  expr   =   Replace(expr,   "]",   ")")  
   
                  expr   =   Replace(expr,   "w",   "10")  
   
                  Try  
                          txtResult.Text   =   Evaluate(expr).ToString   '//结果:163851100  
   
                  Catch   ex   As   Exception  
                          txtResult.Text   =   ex.Message    
                  End   Try  
          End   Sub    
   
  '//============================================  
  '//类   Evaluate    
  '//============================================  
  Imports   System.Text.RegularExpressions  
   
  Module   EvaluateModule  
   
          Function   Evaluate(ByVal   expr   As   String)   As   Double  
                  '   A   number   is   a   sequence   of   digits   optionally   followed   by   a   dot   and    
                  '   another   sequence   of   digits.   The   number   in   parenthesis   in   order   to    
                  '   define   an   unnamed   group.  
                  Const   Num   As   String   =   "(\-?\d+\.?\d*)"  
                  '   List   of   1-operand   functions.  
                  Const   Func1   As   String   =   "(exp|log|log10|abs|sqr|sqrt|sin|cos|tan|asin|acos|atan)"  
                  '   List   of   2-operand   functions.  
                  Const   Func2   As   String   =   "(atan2)"  
                  '   List   of   N-operand   functions.  
                  Const   FuncN   As   String   =   "(min|max)"  
                  '   List   of   predefined   constants.  
                  Const   Constants   As   String   =   "(e|pi)"  
   
                  '   Define   one   Regex   object   for   each   supported   operation.  
                  '   They   are   outside   the   loop,   so   that   they   are   compiled   only   once.  
                  '   Binary   operations   are   defined   as   two   numbers   with   a   symbol   between   them  
                  '   optionally   separated   by   spaces.  
                  Dim   rePower   As   New   Regex(Num   &   "\s*(\^)\s*"   &   Num)  
                  Dim   reAddSub   As   New   Regex(Num   &   "\s*([-+])\s*"   &   Num)  
                  Dim   reMulDiv   As   New   Regex(Num   &   "\s*([*/])\s*"   &   Num)  
                  '   These   Regex   objects   resolve   call   to   functions.   (Case   insensitivity.)  
                  Dim   reFunc1   As   New   Regex(Func1   &   "\(\s*"   &   Num   &   "\s*\)",   _  
                          RegexOptions.IgnoreCase)  
                  Dim   reFunc2   As   New   Regex(Func2   &   "\(\s*"   &   Num   &   "\s*,\s*"   &   Num   _  
                          &   "\s*\)",   RegexOptions.IgnoreCase)  
                  Dim   reFuncN   As   New   Regex(FuncN   &   "\((\s*"   &   Num   &   "\s*,)+\s*"   &   Num   _  
                          &   "\s*\)",   RegexOptions.IgnoreCase)  
                  '   This   Regex   object   drop   a   +   when   it   follows   an   operator.  
                  Dim   reSign1   As   New   Regex("([-+/*^])\s*\+")  
                  '   This   Regex   object   converts   a   double   minus   into   a   plus.  
                  Dim   reSign2   As   New   Regex("\-\s*\-")  
                  '   This   Regex   object   drops   parenthesis   around   a   number.  
                  '   (must   not   be   preceded   by   an   alphanum   char   (it   might   be   a   function   name)  
                  Dim   rePar   As   New   Regex("(?<![A-Za-z0-9])\(\s*([-+]?\d+.?\d*)\s*\)")  
                  '   A   Regex   object   that   tells   that   the   entire   expression   is   a   number  
                  Dim   reNum   As   New   Regex("^\s*[-+]?\d+\.?\d*\s*$")  
   
                  '   The   Regex   object   deals   with   constants.   (Requires   case   insensitivity.)  
                  Dim   reConst   As   New   Regex("\s*"   &   Constants   &   "\s*",   _  
                          RegexOptions.IgnoreCase)  
                  '   This   resolves   predefined   constants.   (Can   be   kept   out   of   the   loop.)  
                  expr   =   reConst.Replace(expr,   AddressOf   DoConstants)  
   
                  '   Loop   until   the   entire   expression   becomes   just   a   number.  
                  Do   Until   reNum.IsMatch(expr)  
                          Dim   saveExpr   As   String   =   expr  
   
                          '   Perform   all   the   math   operations   in   the   source   string.  
                          '   starting   with   operands   with   higher   operands.  
                          '   Note   that   we   continue   to   perform   each   operation   until   there   are  
                          '   no   matches,   because   we   must   account   for   expressions   like   (12*34*56)  
   
                          '   Perform   all   power   operations.  
                          Do   While   rePower.IsMatch(expr)  
                                  expr   =   rePower.Replace(expr,   AddressOf   DoPower)  
                          Loop  
   
                          '   Perform   all   divisions   and   multiplications.  
                          Do   While   reMulDiv.IsMatch(expr)  
                                  expr   =   reMulDiv.Replace(expr,   AddressOf   DoMulDiv)  
                          Loop  
   
                          '   Perform   functions   with   variable   numbers   of   arguments.    
                          Do   While   reFuncN.IsMatch(expr)  
                                  expr   =   reFuncN.Replace(expr,   AddressOf   DoFuncN)  
                          Loop  
   
                          '   Perform   functions   with   2   arguments.    
                          Do   While   reFunc2.IsMatch(expr)  
                                  expr   =   reFunc2.Replace(expr,   AddressOf   DoFunc2)  
                          Loop  
   
                          '   1-operand   functions   must   be   processed   last   to   deal   correctly   with    
                          '   expressions   such   as   SIN(ATAN(1))   before   we   drop   parenthesis    
                          '   pairs   around   numbers.  
                          Do   While   reFunc1.IsMatch(expr)  
                                  expr   =   reFunc1.Replace(expr,   AddressOf   DoFunc1)  
                          Loop  
   
                          '   Discard   +   symbols   (unary   pluses)that   follow   another   operator.  
                          expr   =   reSign1.Replace(expr,   "$1")  
                          '   Simplify   2   consecutive   minus   signs   into   a   plus   sign.  
                          expr   =   reSign2.Replace(expr,   "+")  
   
                          '   Perform   all   additions   and   subtractions.  
                          Do   While   reAddSub.IsMatch(expr)  
                                  expr   =   reAddSub.Replace(expr,   AddressOf   DoAddSub)  
                          Loop  
   
                          '   attempt   to   discard   parenthesis   around   numbers.   We   can   do   this  
                          expr   =   rePar.Replace(expr,   "$1")  
   
                          '   if   the   expression   didn't   change,   we   have   a   syntax   error.  
                          '   this   serves   to   avoid   endless   loops  
                          If   expr   =   saveExpr   Then  
                                  '   if   it   didn't   work,   exit   with   syntax   error   exception.  
                                  Throw   New   SyntaxErrorException()  
                          End   If  
                  Loop  
   
                  '   Return   the   expression,   which   is   now   a   number.  
                  Return   CDbl(expr)  
          End   Function  
   
          '   These   functions   evaluate   the   actual   math   operations.  
          '   In   all   cases   the   Match   object   on   entry   has   groups   that   identify  
          '   the   two   operands   and   the   operator.  
  Top

6 楼MSTOP(陈建华)回复于 2006-04-04 11:09:09 得分 20

 
          Function   DoConstants(ByVal   m   As   Match)   As   String  
                  Select   Case   m.Groups(1).Value.ToUpper  
                          Case   "PI"  
                                  Return   Math.PI.ToString  
                          Case   "E"  
                                  Return   Math.E.ToString  
                  End   Select  
          End   Function  
   
          Function   DoPower(ByVal   m   As   Match)   As   String  
                  Dim   n1   As   Double   =   CDbl(m.Groups(1).Value)  
                  Dim   n2   As   Double   =   CDbl(m.Groups(3).Value)  
                  '   Group(2)   is   always   the   ^   character   in   this   version.  
                  Return   (n1   ^   n2).ToString  
          End   Function  
   
          Function   DoMulDiv(ByVal   m   As   Match)   As   String  
                  Dim   n1   As   Double   =   CDbl(m.Groups(1).Value)  
                  Dim   n2   As   Double   =   CDbl(m.Groups(3).Value)  
                  Select   Case   m.Groups(2).Value  
                          Case   "/"  
                                  Return   (n1   /   n2).ToString  
                          Case   "*"  
                                  Return   (n1   *   n2).ToString  
                  End   Select  
          End   Function  
   
          Function   DoAddSub(ByVal   m   As   Match)   As   String  
                  Dim   n1   As   Double   =   CDbl(m.Groups(1).Value)  
                  Dim   n2   As   Double   =   CDbl(m.Groups(3).Value)  
                  Select   Case   m.Groups(2).Value  
                          Case   "+"  
                                  Return   (n1   +   n2).ToString  
                          Case   "-"  
                                  Return   (n1   -   n2).ToString  
                  End   Select  
          End   Function  
   
          '   These   functions   evaluate   functions.  
   
          Function   DoFunc1(ByVal   m   As   Match)   As   String  
                  '   function   argument   is   2nd   group.  
                  Dim   n1   As   Double   =   CDbl(m.Groups(2).Value)  
                  '   function   name   is   1st   group.  
                  Select   Case   m.Groups(1).Value.ToUpper  
                          Case   "EXP"  
                                  Return   Math.Exp(n1).ToString  
                          Case   "LOG"  
                                  Return   Math.Log(n1).ToString  
                          Case   "LOG10"  
                                  Return   Math.Log10(n1).ToString  
                          Case   "ABS"  
                                  Return   Math.Abs(n1).ToString  
                          Case   "SQR",   "SQRT"  
                                  Return   Math.Sqrt(n1).ToString  
                          Case   "SIN"  
                                  Return   Math.Sin(n1).ToString  
                          Case   "COS"  
                                  Return   Math.Cos(n1).ToString  
                          Case   "TAN"  
                                  Return   Math.Tan(n1).ToString  
                          Case   "ASIN"  
                                  Return   Math.Asin(n1).ToString  
                          Case   "ACOS"  
                                  Return   Math.Acos(n1).ToString  
                          Case   "ATAN"  
                                  Return   Math.Atan(n1).ToString  
                  End   Select  
          End   Function  
   
          Function   DoFunc2(ByVal   m   As   Match)   As   String  
                  '   function   arguments   are   2nd   and   3rd   group.  
                  Dim   n1   As   Double   =   CDbl(m.Groups(2).Value)  
                  Dim   n2   As   Double   =   CDbl(m.Groups(3).Value)  
                  '   function   name   is   1st   group.  
                  Select   Case   m.Groups(1).Value.ToUpper  
                          Case   "ATAN2"  
                                  Return   Math.Atan2(n1,   n2).ToString  
                  End   Select  
          End   Function  
   
          Function   DoFuncN(ByVal   m   As   Match)   As   String  
                  '   function   arguments   are   from   group   2   onward.  
                  Dim   args   As   New   ArrayList()  
                  Dim   i   As   Integer   =   2  
                  '   Load   all   the   arguments   into   the   array.  
                  Do   While   m.Groups(i).Value   <>   ""  
                          '   Get   the   argument,   replace   any   comma   to   space,   and   convert   to   double.  
                          args.Add(CDbl(m.Groups(i).Value.Replace(","c,   "   "c)))  
                          i   +=   1  
                  Loop  
   
                  '   function   name   is   1st   group.  
                  Select   Case   m.Groups(1).Value.ToUpper  
                          Case   "MIN"  
                                  args.Sort()  
                                  Return   args(0).ToString  
                          Case   "MAX"  
                                  args.Sort()  
                                  Return   args(args.Count   -   1).ToString  
                  End   Select  
          End   Function  
   
  End   Module  
  Top

7 楼MSTOP(陈建华)回复于 2006-04-04 11:15:21 得分 0

可以将公式中的变量生成一个临时数据表.  
  将变量的值分别插到临时表中.  
  然后用   SELECT   调用该公式.  
   
  例如:公式中用到变量   W   .那可建一个临时表    
  CREATE   TABLE   #EVTAB   (EVID   INT,W   FLOAT   )  
  INSERT   INTO   #EVTAB   VALUES(1,10)  
   
  然后.处理一下大括号和中括号.  
  STRSQL="SELECT   [{(w-0)*(21-w)}]*(100+[(w-0.5)/0.5]*40)+[{(w-21)*(50-w)}]*[w]*60+[{([w]-51)*(100-w)}]*[w]*55+[[w]-100]*[w]*50   FROM   #EVTAB   WHERE   EVID=1"     '//注:这里括号未处理.  
  该语句返回的结果即是计算结果.  
   
   
  Top

8 楼zsylizard(落日浮云)回复于 2006-04-04 16:51:23 得分 5

编译原理书上都有这方面的例子。Top

9 楼MSTOP(陈建华)回复于 2006-04-05 09:41:31 得分 5

zsylizard(落日浮云)   (   )   信誉:100     2006-04-04   16:51:00     得分:   0      
        编译原理书上都有这方面的例子。  
  ================================================  
  别玩太高深的...高深在绝大多数场合只能坏事.Top

10 楼xinliangyu(yxl)回复于 2006-04-05 09:51:09 得分 0

表达式计算,我还参与几个这类贴子的讨论,搜索一下吧!当然要自己来写表达式的解释器也是很有趣的,不过较费力,相当考验水平。Top

11 楼zyb1235(翟)回复于 2006-04-05 15:57:24 得分 0

MSTOP(陈建华)    
  你给的是两种方法对吗?  
  我还是觉得第一种好一点[非常感谢]Top

12 楼emanlee(造化弄人)回复于 2007-01-04 16:26:54 得分 0

markTop

相关问题

关键词

得分解答快速导航

  • 帖主:zyb1235
  • MSTOP
  • MSTOP
  • zsylizard
  • MSTOP

相关链接

  • CSDN .NET频道
  • .NET类图书
  • C#类图书
  • .NET类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo