您的位置:首页 > 其它

计算 字符串数学表达式

2014-02-10 11:42 155 查看
‘参考自 http://blog.csdn.net/laviewpbt/article/details/1806217 ,并修改了一小点内容(带参数调用时,第二次调用出错问题)

Option Explicit

'定义的各算子的优先级
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         '+

'自定义表达式计算:使用方法 Eval("3+4*exp(4)-sin(4/5)+abs(12/5)")  或带参数的  Eval("X1 + x0 * 2 + x3", 2, 4, 3, 6)
Public Function Eval(ByVal Expression As String, ParamArray Data() As Variant) As Double
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
Dim i As Long
Static DeepLevel As Long

If DeepLevel = 0 Then                                   '因为是递归,所以要防止重复做无用功
Expression = LCase(Trim(Expression))        '删除首尾空格并把字符转换成小写
For Each V In Data
Expression = Replace(Expression, "x" & i, V)
i = i + 1
Next
End If

DeepLevel = DeepLevel + 1

Expression_Len = Len(Expression)                '计算字符串的长度,一定要放在上面代码的下部
If Expression_Len = 0 Then GoTo myend
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 "/"
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) Mod Eval(RightExpression)
Case "+"
Eval = Eval(LeftExpression) + Eval(RightExpression)
Case "-"
Eval = Eval(LeftExpression) - Eval(RightExpression)
End Select
GoTo myend
End If
If Left(Expression, 1) = "(" And Right(Expression, 1) = ")" Then
Eval = Eval(Mid(Expression, 2, Expression_Len - 2))
GoTo myend
End If
If Left(Expression, 1) = "-" Then
Eval = -Eval(Right(Expression, Expression_Len - 1))
GoTo myend
End If
If Left(Expression, 1) = "+" Then
Eval = Eval(Right(Expression, Expression_Len - 1))
GoTo myend
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 = Sin(Eval(RightExpression))
Case "cos("
Eval = Cos(Eval(RightExpression))
Case "tan("
Eval = Tan(Eval(RightExpression))
Case "sqr("
Eval = Sqr(Eval(RightExpression))
Case "abs("
Eval = Abs(Eval(RightExpression))
Case "exp("
Eval = Exp(Eval(RightExpression))
Case "log("
Eval = Log(Eval(RightExpression))
Case "sgn("
Eval = Sgn(Eval(RightExpression))
Case "atn("
Eval = Atn(Eval(RightExpression))
Case "rnd("
Eval = Rnd(Eval(RightExpression))
End Select

GoTo myend
End If
On Error GoTo Errhandle:

Eval = CDbl(Expression)

GoTo myend

Errhandle:
Err.Raise vbObjectError + 1003, "错误", "未知错误发生!"

myend:
DeepLevel = DeepLevel - 1
End Function

Public Function MSScriptEval(ByVal Expression As String) As Double
Dim scr As Object
Set scr = CreateObject("MSScriptControl.ScriptControl")
scr.Language = "vbscript"
MSScriptEval = scr.Eval(Expression)
Set scr = Nothing
End Function
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: