Private Function getweight(oper As String) As Integer
Select Case oper
Case "+", "-"
getweight = 5
Case "*", "/", "\"
getweight = 10
Case "^"
getweight = 15
Case "%"
getweight = 8
Case "("
getweight = 100
Case "#", ")"
getweight = -100
Case Else
getweight = 30
End Select
End Function
Public Function eval(str As String, Optional ByVal size As Long = 2047) As Double
On Error GoTo RE
Dim oper$(), num#(), readnum As Boolean, i&, c$, poper&, pnum&, numbegin&, o$, func, fchar
ReDim oper(size), num(size)
poper = -1&: pnum = -1&
str = LCase(str) + "#"
func = Array("sin", "cos", "ln", "sqrt", "tan", "lg", "log")
fchar = Array("s", "c", "n", "q", "t", "g", "o")
For i = 0& To UBound(func)
str = Replace(str, func(i), fchar(i))
Next i
str = Replace(str, "(-", "(0-")
If Right(str, 1) = "-" Then str = "0" + str
For i = 1& To Len(str)
c = Mid(str, i, 1&)
If (c >= "0" And c <= "9") Or c = "." Or c = "_" Then
If Not readnum Then
readnum = True
numbegin = i
End If
Else
If readnum Then
readnum = False
pnum = pnum + 1&
num(pnum) = Val(Mid(str, numbegin, i - numbegin))
End If
NextOper:
If poper >= 0 Then
o = oper(poper)
If getweight(c) <= getweight(o) Then
If c = ")" And o = "(" Then poper = poper - 1: GoTo Nexti
Select Case o
Case "("
GoTo PushOper
Case "+"
pnum = pnum - 1: num(pnum) = num(pnum) + num(pnum + 1)
Case "-"
pnum = pnum - 1: num(pnum) = num(pnum) - num(pnum + 1)
Case "*"
pnum = pnum - 1: num(pnum) = num(pnum) * num(pnum + 1)
Case "/"
pnum = pnum - 1: num(pnum) = num(pnum) / num(pnum + 1)
Case "\"
pnum = pnum - 1: num(pnum) = CLng(num(pnum)) \ CLng(num(pnum + 1))
Case "%"
pnum = pnum - 1: num(pnum) = CLng(num(pnum)) Mod CLng(num(pnum + 1))
Case "^"
pnum = pnum - 1: num(pnum) = num(pnum) ^ num(pnum + 1)
Case "s"
num(pnum) = Sin(num(pnum))
Case "c"
num(pnum) = Cos(num(pnum))
Case "t"
num(pnum) = Tan(num(pnum))
Case "n"
num(pnum) = Log(num(pnum))
Case "q"
num(pnum) = Sqr(num(pnum))
Case "g"
num(pnum) = Log(num(pnum)) / Log(10)
Case "o"
pnum = pnum - 1: num(pnum) = Log(num(pnum + 1)) / Log(num(pnum))
End Select
poper = poper - 1
GoTo NextOper
End If
End If
PushOper:
poper = poper + 1
oper(poper) = c
End If
Nexti:
Next i
eval = num(0)
Exit Function
RE:
MsgBox "Invalid expression!"
End Function
'ps:字符串解析部分懒得分词,所以说把多字符函数都替换为了单字符;提取数字事懒得区分负号和减号,所以把(-xxxx)替换为(0-xxxx),不合数学规范的负号(如1--5)将出错。
Select Case oper
Case "+", "-"
getweight = 5
Case "*", "/", "\"
getweight = 10
Case "^"
getweight = 15
Case "%"
getweight = 8
Case "("
getweight = 100
Case "#", ")"
getweight = -100
Case Else
getweight = 30
End Select
End Function
Public Function eval(str As String, Optional ByVal size As Long = 2047) As Double
On Error GoTo RE
Dim oper$(), num#(), readnum As Boolean, i&, c$, poper&, pnum&, numbegin&, o$, func, fchar
ReDim oper(size), num(size)
poper = -1&: pnum = -1&
str = LCase(str) + "#"
func = Array("sin", "cos", "ln", "sqrt", "tan", "lg", "log")
fchar = Array("s", "c", "n", "q", "t", "g", "o")
For i = 0& To UBound(func)
str = Replace(str, func(i), fchar(i))
Next i
str = Replace(str, "(-", "(0-")
If Right(str, 1) = "-" Then str = "0" + str
For i = 1& To Len(str)
c = Mid(str, i, 1&)
If (c >= "0" And c <= "9") Or c = "." Or c = "_" Then
If Not readnum Then
readnum = True
numbegin = i
End If
Else
If readnum Then
readnum = False
pnum = pnum + 1&
num(pnum) = Val(Mid(str, numbegin, i - numbegin))
End If
NextOper:
If poper >= 0 Then
o = oper(poper)
If getweight(c) <= getweight(o) Then
If c = ")" And o = "(" Then poper = poper - 1: GoTo Nexti
Select Case o
Case "("
GoTo PushOper
Case "+"
pnum = pnum - 1: num(pnum) = num(pnum) + num(pnum + 1)
Case "-"
pnum = pnum - 1: num(pnum) = num(pnum) - num(pnum + 1)
Case "*"
pnum = pnum - 1: num(pnum) = num(pnum) * num(pnum + 1)
Case "/"
pnum = pnum - 1: num(pnum) = num(pnum) / num(pnum + 1)
Case "\"
pnum = pnum - 1: num(pnum) = CLng(num(pnum)) \ CLng(num(pnum + 1))
Case "%"
pnum = pnum - 1: num(pnum) = CLng(num(pnum)) Mod CLng(num(pnum + 1))
Case "^"
pnum = pnum - 1: num(pnum) = num(pnum) ^ num(pnum + 1)
Case "s"
num(pnum) = Sin(num(pnum))
Case "c"
num(pnum) = Cos(num(pnum))
Case "t"
num(pnum) = Tan(num(pnum))
Case "n"
num(pnum) = Log(num(pnum))
Case "q"
num(pnum) = Sqr(num(pnum))
Case "g"
num(pnum) = Log(num(pnum)) / Log(10)
Case "o"
pnum = pnum - 1: num(pnum) = Log(num(pnum + 1)) / Log(num(pnum))
End Select
poper = poper - 1
GoTo NextOper
End If
End If
PushOper:
poper = poper + 1
oper(poper) = c
End If
Nexti:
Next i
eval = num(0)
Exit Function
RE:
MsgBox "Invalid expression!"
End Function
'ps:字符串解析部分懒得分词,所以说把多字符函数都替换为了单字符;提取数字事懒得区分负号和减号,所以把(-xxxx)替换为(0-xxxx),不合数学规范的负号(如1--5)将出错。