您的位置:程序门 -> vb -> 基础类



请教表达式解释器增加自定义函数


[收藏此页] [打印本页]选择字色:背景色:字体:[][][]


请教表达式解释器增加自定义函数
发表于:2007-12-30 01:09:53 楼主
以下代码取自:
laviewpbt的专栏
http://blog.csdn.net/laviewpbt/archive/2007/09/29/1806217.aspx

我做了部分改动主要想分解表达式,如:
    "12\x1+x3+exp(sin(3,4),4,x1,x2)+x2"

目的分解成:(这里假设   sin   和   exp   是个多参数自定义函数)
    变量1   =   12   \   x1
    变量2   =   变量1   +   x3
    变量3   =   sin   3,4
    变量4   =   exp   变量3,4,x1,x2
    变量5   =   变量2   +   变量4
    变量6   =   变量5   +   x2

现在问题是我不知道如何处理逗号,下面是实际分解结果:
    变量1   =   12   \   x1
    变量2   =   变量1   +   x3
    变量3   =   exp   sin(3,4),4,x1,x2
    变量4   =   变量2   +   变量3
    变量5   =   变量4   +   x2

'=======================代码===========================
'需要   text1   command1
'定义的各算子的优先级
private   const   prec_none   =   11                 '
private   const   prec_unary   =   10               '实际中没有用到
private   const   prec_power   =   9                 '^
private   const   prec_times   =   8                 '*
private   const   prec_div   =   7                     '/
private   const   prec_int_div   =   6             '\
private   const   prec_mod   =   5                     'mod
private   const   prec_plus   =   4                   '+

private   m_变量   as   long

private   function   eval(byval   expression   as   string,   paramarray   data()   as   variant)   as   string
        dim   is_unary                 as   boolean
        dim   next_unary             as   boolean
        dim   brackets                 as   integer
        dim   pos                           as   integer
        dim   expression_len     as   integer
        dim   char                         as   string
        dim   leftexpression     as   string
        dim   rightexpression   as   string
        dim   value                       as   string
        dim   status                     as   long
        dim   best_pos           as   integer
        dim   best_prec           as   integer
        dim   temp1     as   double
        dim   temp2               as   double
        dim   v   as   variant
        static   i   as   long
        if   i   =   0   then                                                                       '因为是递归,所以要防止重复做无用功
                expression   =   lcase(trim(expression))                 '删除首尾空格并把字符转换成小写
                for   each   v   in   data
                        'expression   =   replace(expression,   "x"   &   i,   v)
                        i   =   i   +   1
                next
        end   if
        expression_len   =   len(expression)                                 '计算字符串的长度,一定要放在上面代码的下部
        if   expression_len   =   0   then   exit   function
        is_unary   =   true                                                                   '如果有+或-,则是单元运算符
        best_prec   =   prec_none                                                       '到目前为止我们什么也没得到
        for   pos   =   1   to   expression_len
                char   =   mid(expression,   pos,   1)                             '检查下一个字符
                next_unary   =   false
                if   char   =   "   "   then                                                     '跳过空格
                        next_unary   =   is_unary
                elseif   char   =   "("   then
                        brackets   =   brackets   +   1                                   '增加括号的个数
                        next_unary   =   true
                elseif   char   =   ")"   then
                        brackets   =   brackets   -   1                                   '减少括号的个数
                        next_unary   =   false
                        if   brackets   <   0   then                                         '左右括号的个数不配套
                                err.raise   vbobjecterror   +   1001,   "错误",   "表达式中左右括号的个数不配套"
                        end   if
                elseif   brackets   =   0   then
                        if   char   =   "^"   or   char   =   "*"   or   char   =   "/"   or   char   =   "\"   or   char   =   "%"   or   char   =   "+"   or   char   =   "-"   then
                                next_unary   =   true
                                select   case   char
                                case   "^"
                                        if   best_prec   > =   prec_power   then
                                                best_prec   =   prec_power
                                                best_pos   =   pos
                                        end   if
                                case   "*",   "/"
                                        if   best_prec   > =   prec_times   then
                                                best_prec   =   prec_times
                                                best_pos   =   pos
                                        end   if
                                 
                                case   "\"
                                        if   best_prec   > =   prec_int_div   then
                                                best_prec   =   prec_int_div
                                                best_pos   =   pos
                                        end   if
                             
                                case   "%"
                                        if   best_prec   > =   prec_mod   then
                                                best_prec   =   prec_mod
                                                best_pos   =   pos
                                        end   if
                                case   "+",   "-"
                                        if   (not   is_unary)   and   best_prec   > =   prec_plus   then
                                                best_prec   =   prec_plus
                                                best_pos   =   pos
                                        end   if
                                end   select
                        end   if
                end   if
                is_unary   =   next_unary
        next
       
        if   brackets   <>   0   then
                err.raise   vbobjecterror   +   1002,   "错误",   "表达式中丢失一个   )"
        end   if
       
        if   best_prec   <   prec_none   then
                leftexpression   =   left(expression,   best_pos   -   1)
                rightexpression   =   right(expression,   expression_len   -   best_pos)
                select   case   mid(expression,   best_pos,   1)
                case   "^"
                        eval   =   方根(eval(leftexpression),   eval(rightexpression))
                case   "*"
                        eval   =   乘法(eval(leftexpression),   eval(rightexpression))
                case   "/"
                        eval   =   除法(eval(leftexpression),   eval(rightexpression))
                        'temp1   =   eval(rightexpression)
                        'temp2   =   eval(leftexpression)
                        'if   temp1   =   0   then
                        '         eval   =   0
                        'else
                        '         eval   =   temp2   /   temp1
                        'end   if
                case   "\"
                        eval   =   整除(eval(leftexpression),   eval(rightexpression))
                case   "%"
                        eval   =   取模(eval(leftexpression),   eval(rightexpression))
                case   "+"
                        eval   =   加法(eval(leftexpression),   eval(rightexpression))
                case   "-"
                        eval   =   减法(eval(leftexpression),   eval(rightexpression))
                end   select
                exit   function
        end   if
        if   left(expression,   1)   =   "("   and   right(expression,   1)   =   ")"   then
                eval   =   eval(mid(expression,   2,   expression_len   -   2))
                exit   function
        end   if
        if   left(expression,   1)   =   "-"   then
                eval   =   -eval(right(expression,   expression_len   -   1))
                exit   function
        end   if
        if   left(expression,   1)   =   "+"   then
                eval   =   eval(right(expression,   expression_len   -   1))
                exit   function
        end   if
        if   expression_len   >   5   and   right(expression,   1)   =   ")"   then
                leftexpression   =   left(expression,   4)
                rightexpression   =   mid(expression,   5,   expression_len   -   5)
               
                '可根据逗号分割多个参数后代入,但是如果参数中仍包含有表达式如何?
                select   case   leftexpression
                case   "sin("
                        eval   =   sinn(eval(rightexpression))
                case   "cos("
                        eval   =   cosn(eval(rightexpression))
                case   "tan("
                        eval   =   tann(eval(rightexpression))
                case   "sqr("
                        eval   =   sqrn(eval(rightexpression))
                case   "abs("
                        eval   =   absn(eval(rightexpression))
                case   "exp("
                        eval   =   expn(eval(rightexpression))
                case   "log("
                        eval   =   logn(eval(rightexpression))
                case   "sgn("
                        eval   =   sgnn(eval(rightexpression))
                case   "atn("
                        eval   =   atnn(eval(rightexpression))
                case   "rnd("
                        eval   =   rndn(eval(rightexpression))
                end   select
               
                exit   function
        end   if
        on   error   goto   errhandle:
        eval   =   expression
        exit   function
errhandle:
        err.raise   vbobjecterror   +   1003,   "错误",   "未知错误发生!"
end   function


发表于:2007-12-30 01:10:401楼 得分:0
private   function   方根(n   as   string,   b   as   string)   as   string
        m_变量   =   m_变量   +   1
        方根   =   "变量"   &   format(m_变量)
        evalshow   "变量"   &   format(m_变量)   &   "   =   "   &   n   &   "   ^   "   &   b
end   function

private   function   乘法(n   as   string,   b   as   string)   as   string
        m_变量   =   m_变量   +   1
        乘法   =   "变量"   &   format(m_变量)
        evalshow   "变量"   &   format(m_变量)   &   "   =   "   &   n   &   "   *   "   &   b
end   function

private   function   加法(n   as   string,   b   as   string)   as   string
        m_变量   =   m_变量   +   1
        加法   =   "变量"   &   format(m_变量)
        evalshow   "变量"   &   format(m_变量)   &   "   =   "   &   n   &   "   +   "   &   b
end   function

private   function   减法(n   as   string,   b   as   string)   as   string
        m_变量   =   m_变量   +   1
        减法   =   "变量"   &   format(m_变量)
        evalshow   "变量"   &   format(m_变量)   &   "   =   "   &   n   &   "   -   "   &   b
end   function

private   function   除法(n   as   string,   b   as   string)   as   string
        m_变量   =   m_变量   +   1
        除法   =   "变量"   &   format(m_变量)
        evalshow   "变量"   &   format(m_变量)   &   "   =   "   &   n   &   "   /   "   &   b
end   function

private   function   整除(n   as   string,   b   as   string)   as   string
        m_变量   =   m_变量   +   1
        整除   =   "变量"   &   format(m_变量)
        evalshow   "变量"   &   format(m_变量)   &   "   =   "   &   n   &   "   \   "   &   b
end   function

private   function   取模(n   as   string,   b   as   string)   as   string
        m_变量   =   m_变量   +   1
        取模   =   "变量"   &   format(m_变量)
        evalshow   "变量"   &   format(m_变量)   &   "   =   "   &   n   &   "   mod   "   &   b
end   function

private   function   cosn(n   as   string)   as   string
        m_变量   =   m_变量   +   1
        cosn   =   "变量"   &   format(m_变量)
        evalshow   "变量"   &   format(m_变量)   &   "   =   cos   "   &   n
end   function

private   function   sgnn(n   as   string)   as   string
        m_变量   =   m_变量   +   1
        sgnn   =   "变量"   &   format(m_变量)
        evalshow   "变量"   &   format(m_变量)   &   "   =   sgn   "   &   n
end   function

private   function   atnn(n   as   string)   as   string
        m_变量   =   m_变量   +   1
        atnn   =   "变量"   &   format(m_变量)
        evalshow   "变量"   &   format(m_变量)   &   "   =   atn   "   &   n
end   function

private   function   rndn(n   as   string)   as   string
        m_变量   =   m_变量   +   1
        rndn   =   "变量"   &   format(m_变量)
        evalshow   "变量"   &   format(m_变量)   &   "   =   rnd   "   &   n
end   function

private   function   tann(n   as   string)   as   string
        m_变量   =   m_变量   +   1
        tann   =   "变量"   &   format(m_变量)
        evalshow   "变量"   &   format(m_变量)   &   "   =   tan   "   &   n
end   function

private   function   sqrn(n   as   string)   as   string
        m_变量   =   m_变量   +   1
        sqrn   =   "变量"   &   format(m_变量)
        evalshow   "变量"   &   format(m_变量)   &   "   =   sqr   "   &   n
end   function

private   function   absn(n   as   string)   as   string
        m_变量   =   m_变量   +   1
        absn   =   "变量"   &   format(m_变量)
        evalshow   "变量"   &   format(m_变量)   &   "   =   abs   "   &   n
end   function

private   function   expn(n   as   string)   as   string
        m_变量   =   m_变量   +   1
        expn   =   "变量"   &   format(m_变量)
        evalshow   "变量"   &   format(m_变量)   &   "   =   exp   "   &   n
end   function

private   function   logn(n   as   string)   as   string
        m_变量   =   m_变量   +   1
        logn   =   "变量"   &   format(m_变量)
        evalshow   "变量"   &   format(m_变量)   &   "   =   log   "   &   n
end   function

private   function   sinn(n   as   string)   as   string
        m_变量   =   m_变量   +   1
        sinn   =   "变量"   &   format(m_变量)
        evalshow   "变量"   &   format(m_变量)   &   "   =   sin   "   &   n
end   function

private   sub   command1_click()
        'eval   "x1+x0*2+x3\x4+exp(sin(3),4)",   2,   4,   3,   6
        eval   "12\x1+x3+exp(sin(3,4),4,x1,x2)+x2",   2,   4,   3,   6
end   sub

private   sub   evalshow(s   as   string)
        text1.text   =   text1.text   &   s   &   chr(13)   &   chr(10)
end   sub

private   sub   form_load()
        text1.text   =   ""
end   sub


快速检索

最新资讯
热门点击