打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
功能强大的表达式计算函数(模块)
'功能强大的表达式计算模块
'作者董凯颂
'作者单位安徽省安庆市花凉亭灌区管理局
'电子信箱:dongkaisong@163.com
'Web site:http://hexun.com/headbegger/
'2005年9月10日
'鄙视匿名抄袭和剽切,转载或传播、修改发布时请注明软件原作者

'******************************计算用户输入的表达式******************************************************
'********************************************************************************************************
'*支持+-*、/、^、()、常用函数,函数书写不分大小写,中间允许有空格,但参数表达式必须放在括号内         *
'*支持的函数包括sin()正弦、cos()余弦、tan()正切、asin()反正弦、acos()反余弦、atn()反正切、ln()自然对数*
'*log()以10为底的常用对数、exp()e的幂、jch()自然数阶乘、sqr()平方根、int()取整、pi常数π                *
'*因为排错功能有限,使用时,请正确输入算式。三角函数的参数单位为弧度,使用函数时注意函数的定义域         *
'********************************************************************************************************


Const pi As String = "3.14159265358979"


'两个大数之积),为下面定义阶函数乘用
Private Function multi(ByVal x As String, ByVal Y As String) As String
    Dim result As Variant
    Dim xl As Long, yl As Long, temp As Long, i As Long
    xl = Len(Trim(x))
    yl = Len(Trim(Y))
    ReDim result(1 To xl + yl) '重定义数组,因为后面用Erase清空了数组
    For i = 1 To xl
        For temp = 1 To yl
            result(i + temp) = result(i + temp) + Val(Mid(x, i, 1)) * Val(Mid(Y, temp, 1))
            DoEvents
        Next
    Next
    For i = xl + yl To 2 Step -1
        temp = result(i) \ 10 'temp定义为整型,它只取 result(i) \ 10的整数部分
        result(i) = result(i) Mod 10
        result(i - 1) = result(i - 1) + temp '把进位的数加在高位上
    Next
    If result(1) = "0" Then result(1) = ""
        multi = Join(result, "") 'join函数把result数组里的元数连接起来
    Erase result '清空数组
End Function

'定义阶乘n! ,n为正整数,
Private Function JCh(ByVal x As String) As String
    Dim a() As String, i As Long, n As Long
'    小数自动取整,负数取正
    n = Val(x):  n = Abs(n):  n = Int(n)
    If n = 0 Then
        JCh = 1
        Exit Function
    End If
    ReDim a(1 To n)
    a(1) = 1
    For i = 2 To n
        a(i) = multi(a(i - 1), i)
    Next
    JCh = CStr(a(n))
End Function

Private Function Asin(xx As String) As String   '定义反正弦函数
    Dim x As Double
    If Not IsNumeric(xx) Then Exit Function
    x = Val(xx)
    If Abs(x) > 1 Then
        MsgBox "无效的参数。", vbOKOnly + vbExclamation, "错误!"
        Exit Function
    End If
    Asin = CStr(Atn(x / Sqr(1 - x * x)))
End Function

Private Function Acos(xx As String) As String  '定义反余弦函数
    Dim x As Double
    If Not IsNumeric(xx) Then Exit Function
    x = Val(xx)
    If Abs(x) > 1 Then
        MsgBox "无效的参数。", vbOKOnly + vbExclamation, "错误!"
        Exit Function
    End If
    Acos = CStr(Val(pi) / 2 - Val(Asin(xx)))
End Function

' 取出一个字符
' 参数 Str1 处理的字符串
' 返回 字符串的第一个字符
'        Str1 成为被取后的字符串
Private Function ReadChar(Str1 As String) As String
  ReadChar = ""
  If Str1 = "" Then Exit Function
  ReadChar = Left(Str1, 1)
  Str1 = Right(Str1, Len(Str1) - 1)
End Function

' 退回一个字符
' 参数 Str1 处理的字符串
'        AChar 要退回的字符
' 返回 Str1 被退回后的字符串
Private Function RetChar(Str1 As String, AChar As String) As String
  Str1 = AChar & Str1
  RetChar = Str1
End Function
'
'检查字符串的合法性***************************************
Private Function CheckString(Str1 As String) As String
    On Error Resume Next
   Dim C1 As String
   '检查是否为空
   If Str1 = "" Then
      Exit Function
   End If
                                            
   '去掉所有空格
   Str1 = Replace(Str1, " ", "")
   '检查非法书写错误
   C1 = Left(Str1, 1)
   If C1 = "+" Or C1 = "*" Or C1 = "/" Or C1 = ")" Then
        MsgBox "计算式错误。", vbOKOnly + vbExclamation, "错误!"
        Exit Function
   End If
   C1 = Right(Str1, 1)
      If C1 = "+" Or C1 = "*" Or C1 = "/" Or C1 = "(" Or C1 = "-" Then
        MsgBox "计算式错误。", vbOKOnly + vbExclamation, "错误!"
        Exit Function
   End If
   '检查该字符串中是否有非法字符
   '检查的方法是将所有合法字符全部替换成空
   '替换完后如果该字符串中还有字符,则说明包含非法字符
   Dim StrTemp As String
   StrTemp = UCase(Str1)
   StrTemp = Replace(StrTemp, "SIN", "")  '正弦
   StrTemp = Replace(StrTemp, "COS", "")  '余弦
   StrTemp = Replace(StrTemp, "LOG", "")  '常用对数
   StrTemp = Replace(StrTemp, "EXP", "")  '常数e为底的幂
   StrTemp = Replace(StrTemp, "JCH", "")  '阶乘
   StrTemp = Replace(StrTemp, "TAN", "")  '正切
   StrTemp = Replace(StrTemp, "ASIN", "") '反正弦
   StrTemp = Replace(StrTemp, "ACOS", "") '反余弦
   StrTemp = Replace(StrTemp, "ATN", "")  '反正切
   StrTemp = Replace(StrTemp, "LN", "")   '自然对数
   StrTemp = Replace(StrTemp, "PI", "")   '常数π
   StrTemp = Replace(StrTemp, "INT", "")  '取整
   StrTemp = Replace(StrTemp, "SQR", "")  '平方根
   StrTemp = Replace(StrTemp, "+", "")
   StrTemp = Replace(StrTemp, "-", "")
   StrTemp = Replace(StrTemp, "*", "")
   StrTemp = Replace(StrTemp, "/", "")
   StrTemp = Replace(StrTemp, "^", "")    '幂
   StrTemp = Replace(StrTemp, "0", "")
   StrTemp = Replace(StrTemp, "1", "")
   StrTemp = Replace(StrTemp, "2", "")
   StrTemp = Replace(StrTemp, "3", "")
   StrTemp = Replace(StrTemp, "4", "")
   StrTemp = Replace(StrTemp, "5", "")
   StrTemp = Replace(StrTemp, "6", "")
   StrTemp = Replace(StrTemp, "7", "")
   StrTemp = Replace(StrTemp, "8", "")
   StrTemp = Replace(StrTemp, "9", "")
   StrTemp = Replace(StrTemp, "(", "")
   StrTemp = Replace(StrTemp, ")", "")
   StrTemp = Replace(StrTemp, ".", "")
   If StrTemp <> "" Then
      MsgBox "计算式错误或包含有非法字符。", vbOKOnly + vbExclamation, "错误!"
      Exit Function
   End If
  
   '检查括号是否匹配,括号位置、运算符位置是否有错误
   Dim i As Integer, s1 As Integer, s2 As Integer
   StrTemp = Str1
   C1 = ReadChar(StrTemp)
   i = i + 1
   Do While C1 <> ""
        Select Case C1
        Case "("
            If Mid(Str1, i + 1, 1) = "." Or Mid(Str1, i + 1, 1) = ")" Or Mid(Str1, i + 1, 1) = "+" _
               Or Mid(Str1, i + 1, 1) = "*" Or Mid(Str1, i + 1, 1) = "/" Or Mid(Str1, i + 1, 1) = "^" Then
                MsgBox "计算式错误。", vbOKOnly + vbExclamation, "错误!"
                 Exit Function
            ElseIf i > 1 Then
                    If IsNumeric(Mid(Str1, i - 1, 1)) Or Mid(Str1, i - 1, 1) = ")" Or Mid(Str1, i - 1, 1) = "." Then
                        MsgBox "计算式错误。", vbOKOnly + vbExclamation, "错误!"
                        Exit Function
                    End If
            End If
            s1 = s1 + 1
            If s1 < s2 Then
                 MsgBox "括号不匹配或计算式错误。", vbOKOnly + vbExclamation, "错误!"
                 Exit Function
            End If
        Case ")"
            If (IsNumeric(Mid(Str1, i - 1, 1)) Or Mid(Str1, i - 1, 1) = ")") And (Mid(Str1, i + 1, 1) = ")" Or Mid(Str1, i + 1, 1) = "+" _
               Or Mid(Str1, i + 1, 1) = "*" Or Mid(Str1, i + 1, 1) = "/" Or Mid(Str1, i + 1, 1) = "^" Or Mid(Str1, i + 1, 1) = "-" Or Mid(Str1, i + 1, 1) = "") Then
            Else
                MsgBox "计算式错误。", vbOKOnly + vbExclamation, "错误!"
                 Exit Function
            End If
            s2 = s2 + 1
            If s1 < s2 Then
                 MsgBox "括号不匹配或计算式错误。", vbOKOnly + vbExclamation, "错误!"
                 Exit Function
            End If
  
        Case "+", "*", "/", "^", "-"
            If Mid(Str1, i + 1, 1) = "*" Or Mid(Str1, i + 1, 1) = "/" Or Mid(Str1, i + 1, 1) = "^" Or Mid(Str1, i + 1, 1) = "-" Or Mid(Str1, i + 1, 1) = "+" Or Mid(Str1, i + 1, 1) = "." Then
                MsgBox "计算式错误。", vbOKOnly + vbExclamation, "错误!"
                Exit Function
            End If
        End Select
        
        C1 = ReadChar(StrTemp)
        i = i + 1
   Loop
   If s1 <> s2 Then
      MsgBox "括号不匹配,请仔细检查!", vbOKOnly + vbExclamation, "错误!"
      Exit Function
   End If
   '检查完毕*************************************************
   Str1 = UCase(Str1)
   Str1 = Replace(Str1, "PI", pi)
   CheckString = Str1
End Function

' 读入数字
' 参数 Str1 处理的字符串
' 返回  取到的数字, "" 为错误!
'        Str1 处理后字符串
Private Function ReadNumber(Str1 As String) As String
  Dim C1 As String, i As Integer
  Dim rets As String
  rets = ""
  C1 = ReadChar(Str1)
  i = i + 1
  Do While C1 <> ""
    If i = 1 And C1 = "-" Then
        If Mid(Str1, 1, 1) = "(" Then    '处理括号前面的负号
            rets = DealBlank(Str1)
            rets = C1 & rets
            Exit Do
        ElseIf IsNumeric(Mid(Str1, 1, 1)) Then   '处理负数
            rets = C1
        End If
    Else
        If (C1 >= "0" And C1 <= "9") Or C1 = "." Then
          rets = rets & C1
        Else
          RetChar Str1, C1
          Exit Do
        End If
    End If
    
    C1 = ReadChar(Str1)
    i = i + 1
  Loop
  If Not IsNumeric(rets) Then
  MsgBox rets
    MsgBox "数字输入错误,请仔细检查!", vbOKOnly + vbExclamation, "错误!"
    rets = ""
  End If
  ReadNumber = rets
End Function

' 读入操作符
' 参数 Str1 处理的字符串
' 返回  取到的操作符, "" 为错误!
'        Str1 处理后字符串
Private Function ReadOp(Str1 As String) As String
    Dim C1 As String
    Dim rets As String
    C1 = ReadChar(Str1)
    If C1 = "*" Or C1 = "-" Or C1 = "+" Or C1 = "/" Or C1 = "^" Then
        ReadOp = C1
    Else
        RetChar Str1, C1
        ReadOp = ""
    End If
End Function

' 读入函数      注意函数必须带括号
' 参数 Str1 处理的字符串
' 返回  取到的函数值, "" 为错误!
'        Str1 处理后字符串

Private Function ReadFunction(Str1 As String) As String
  On Error GoTo err
  Dim C1 As String, C2 As String

  C1 = ReadChar(Str1)
  Do While C1 <> "" And C1 <> "("
    C2 = C2 & C1
    C1 = ReadChar(Str1)
  Loop
  RetChar Str1, C1
  Select Case Trim(UCase(C2))
    Case "SIN"    ' 正弦
      C1 = DealBlank(Str1)
      ReadFunction = CStr(Sin(Val(C1)))
    Case "COS"    ' 余弦
      C1 = DealBlank(Str1)
      ReadFunction = CStr(Cos(Val(C1)))
    Case "ASIN"    ' 反正弦
      C1 = DealBlank(Str1)
      ReadFunction = Asin(C1)
    Case "ACOS"    ' 反余弦
      C1 = DealBlank(Str1)
      ReadFunction = Acos(Val(C1))
    Case "TAN"    ' 正切
      C1 = DealBlank(Str1)
      ReadFunction = CStr(Tan(Val(C1)))
    Case "ATN"    ' 反正切
      C1 = DealBlank(Str1)
      ReadFunction = CStr(Atn(Val(C1)))
    Case "LN"    ' 自然对数
      C1 = DealBlank(Str1)
      If Val(C1) <= 0 Then MsgBox "算式错误,对数函数的真数必须为正数,请仔细检查!", vbOKOnly + vbExclamation, "错误!"
      ReadFunction = Log(Val(C1))
    Case "EXP"    ' e的幂
      C1 = DealBlank(Str1)
      ReadFunction = CStr(Exp(Val(C1)))
    Case "LOG"    ' 常用对数
      C1 = DealBlank(Str1)
      If Val(C1) <= 0 Then MsgBox "算式错误,对数函数的真数必须为正数,请仔细检查!", vbOKOnly + vbExclamation, "错误!"
      ReadFunction = Log(Val(C1)) / Log(10)
    Case "JCH"    ' 阶乘
      C1 = DealBlank(Str1)
      ReadFunction = JCh(C1)
    Case "SQR"    ' 平方根
      C1 = DealBlank(Str1)
      If Val(C1) < 0 Then MsgBox "算式错误,不支持负数开平方!", vbOKOnly + vbExclamation, "错误!"
      ReadFunction = CStr(Sqr(Val(C1)))
    Case "INT"    ' 取整
      C1 = DealBlank(Str1)
      ReadFunction = CStr(Int(Val(C1)))
  End Select
err:
End Function


' 取下一个数,数值或函数值或括号里的值
' 参数 Str1   处理的字符串
' 返回  取到的函数值, "" 为错误!
'        Str1 处理后字符串
Private Function GetValue(Str1 As String) As String
  Dim C1 As String

  C1 = ReadChar(Str1)
  RetChar Str1, C1
  Select Case C1
    Case "("
      GetValue = DealBlank(Str1)
    Case "0" To "9", "-"
      GetValue = ReadNumber(Str1)
    Case Else
      GetValue = ReadFunction(Str1)
  End Select
End Function

Private Function GetExp(Str1 As String) As String
    Dim Val1 As String, Op1 As String

    Val1 = GetValue(Str1)
    Op1 = ReadOp(Str1)
    GetExp = SinglCal(Str1, Val1, Op1)
End Function


Private Function CompStr(Val1, Op, Val2) As String
    On Error GoTo err
    Dim NewVal
    Select Case Op
      Case "-"
        NewVal = Val(Val1) - Val(Val2)
      Case "+"
        NewVal = Val(Val1) + Val(Val2)
      Case "*"
        NewVal = Val(Val1) * Val(Val2)
      Case "/"
        If Val(Val2) <> 0 Then
          NewVal = Val(Val1) / Val(Val2)
        Else
           MsgBox "算式错误,导致了0作除数!", vbOKOnly + vbExclamation, "错误!"
        End If
      Case "^"
        If Val(Val1) = 0 And Val(Val2) < 0 Then
          MsgBox "算式错误,导致了0作除数!", vbOKOnly + vbExclamation, "错误!"
        Else
          NewVal = Val(Val1) ^ Val(Val2)
        End If
      Case Else
        NewVal = Val1
    End Select
    CompStr = CStr(NewVal)
err:
End Function

'计算表达式函数入口
Public Function Start(Str1 As String) As String
    Dim strCal As String
    strCal = CheckString(Str1)
    Start = GetExp(strCal)
End Function

'处理括号
' 参数 Str1   处理的字符串
' 返回  括号中表达式计算后的数值, "" 为错误!
'        Str1 处理后字符串
Private Function DealBlank(Str1 As String) As String
    Dim C1 As String, C2 As String, StrTem As String
    Dim N1 As Integer, N2 As Integer, N3 As Integer
    StrTem = Str1
    C1 = ReadChar(StrTem)
    N1 = N1 + 1
    N3 = N3 + 1
    Do While C1 <> "" And N1 <> N2
        C1 = ReadChar(StrTem)
        If C1 = "(" Then N1 = N1 + 1
        If C1 = ")" Then N2 = N2 + 1
        N3 = N3 + 1
    Loop
    If N1 <> N2 Then
        MsgBox "括号不匹配。", vbOKOnly + vbExclamation, "错误!"
        Exit Function
    End If
    
    C1 = Left(Str1, N3)
    C1 = Mid(C1, 2, Len(C1) - 2)
    C2 = Mid(Str1, N3 + 1)
    Str1 = C2
    DealBlank = GetExp(C1)
End Function
'判断运算级别,opt2级高于opt1,则值为True
Private Function ComDegree(opt1, opt2) As Boolean
    Select Case opt1
    Case "+", "-"
        If opt2 = "+" Or opt2 = "-" Then
            ComDegree = False
        Else
            ComDegree = True
        End If
    Case "*", "/"
        If opt2 = "^" Then
           ComDegree = True
        Else
           ComDegree = False
        End If
    Case "^"
        ComDegree = False
    End Select
End Function

'只有一个运算符Op1
Private Function SinglCal(Str1 As String, Val1 As String, Op1 As String) As String
Dim Val2 As String, Op2 As String
    If Op1 <> "" Then
        Val2 = GetValue(Str1)
        Op2 = ReadOp(Str1)
        SinglCal = TwoCal(Str1, Val1, Val2, Op1, Op2)
    Else
        SinglCal = Val1
    End If
End Function

'有二个运算符Op1、Op2
Private Function TwoCal(Str1 As String, Val1 As String, Val2 As String, _
        Op1 As String, Op2 As String) As String
    Dim Val3 As String, Op3 As String
    If Op2 <> "" Then
        If Not (ComDegree(Op1, Op2)) Then
            Val1 = CompStr(Val1, Op1, Val2)
            Op1 = Op2
            TwoCal = SinglCal(Str1, Val1, Op1)
        Else
            Val3 = GetValue(Str1)
            Op3 = ReadOp(Str1)
            TwoCal = ThreeCal(Str1, Val1, Val2, Val3, Op1, Op2, Op3)
        End If
    Else
        Val1 = CompStr(Val1, Op1, Val2)
        Op1 = ""
        TwoCal = SinglCal(Str1, Val1, Op1)
    End If
End Function

'有三个运算符
Private Function ThreeCal(Str1 As String, Val1 As String, Val2 As String, _
        Val3 As String, Op1 As String, Op2 As String, Op3 As String) As String
    Dim Val4 As String, Op4 As String
    If Op3 <> "" Then
        If ComDegree(Op2, Op3) Then
            Val4 = GetValue(Str1)
            Op4 = ReadOp(Str1)
            ThreeCal = FourCal(Str1, Val1, Val2, Val3, Val4, Op1, Op2, Op3, Op4)
        Else
            Val2 = CompStr(Val2, Op2, Val3)
            Op2 = Op3
            ThreeCal = TwoCal(Str1, Val1, Val2, Op1, Op2)
        End If
    Else         ' Op3 = ""
        Val2 = CompStr(Val2, Op2, Val3)
        Val1 = CompStr(Val1, Op1, Val2)
        Op1 = ""
        ThreeCal = SinglCal(Str1, Val1, Op1)
    End If
End Function

'有四个运算符
Private Function FourCal(Str1 As String, Val1 As String, Val2 As String, _
        Val3 As String, Val4 As String, Op1 As String, Op2 As String, _
        Op3 As String, Op4 As String) As String
    If Op4 <> "" Then
        Val3 = CompStr(Val3, Op3, Val4)
        Op3 = Op4
        FourCal = ThreeCal(Str1, Val1, Val2, Val3, Op1, Op2, Op3)
    Else
        Val3 = CompStr(Val3, Op3, Val4)
        Val2 = CompStr(Val2, Op2, Val3)
        Val1 = CompStr(Val1, Op1, Val2)
        Op1 = ""
        FourCal = SinglCal(Str1, Val1, Op1)
    End If
End Function
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
运动控制卡应用开发教程之VB6.0
vb登录界面设计笔记(连接SQLServer2000数据库)
vb 杂记
自用的一个vb类
strchr函数
javascript函数库
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服