关于自定义表达式的计算的类,请指点(VB2005代码)
[code=VB.NET]
'自定义表达式的计算,可以处理括号、SIN 、COS、TAN 、CTAN、阶乘、倒数、
'常数PI、平方、立方、幂的计算、log、ln
'可以定义角度制或弧度制来计算三角函数
'阶乘计算要求数值小于等于160
'
'作者GYP 2011年4月
Public Class gypZDYBDS
Private mySubStr() As String '子字符串数组
Private myVal() As String '存放计算数数组
Private myCaozuoF() As String '存放操作符数组
Private caozuofNum As Integer = 0 '操作符数量
Private myJieGuo As String = "" '最后的结果
Public Huduzhi As Boolean = False '角度弧度设置开关,False为角度制
Private jieguoYN As String = "" '返回计算结果是否正确
Public Function gypJieGuo(ByVal s As String) As String
If s = "" Then
myJieGuo = "没有什么可计算的"
Else
fenjieKhtoJS(s)
End If
Return myJieGuo
End Function
Private Function canJiS(ByVal s As String) As Boolean
'判断字符串长度及左、右括号数量,若字符串长度小于3或者左、右括号数量不相等,则返回“false”
Dim i As Integer
Dim zuokhnum, youkhnum As Integer '左括号及右括号数量
If s.Length >= 3 Then
zuokhnum = 0
youkhnum = 0
For i = 0 To s.Length - 1
If s.Substring(i, 1) = "(" Then zuokhnum += 1
If s.Substring(i, 1) = ")" Then youkhnum += 1
Next
If zuokhnum <> youkhnum Then
Return False
Else
Return True
End If
Else
If ynCF(s) Then
Return False
Else
If s.Length = 1 And ynSZ(s) Then
Return True
ElseIf s.Substring(0, 1) = "-" And ynSZ(s.Substring(1, s.Length - 1)) Then '字符串长度为2的负数
Return True
ElseIf s.Substring(1, 1) = "!" And ynSZ(s.Substring(0, 1)) Then '字符串长度为2的阶乘
Return True
Else
Return False
End If
End If
End If
End Function
Private Function ynCF(ByVal s As String) As Boolean
'判断一个字符串是否为操作符
Return False
Select Case s.Length
Case 0
Return False
Case 1
If s = "+" Or s = "-" Or s = "*" Or s = "/" Or s = "!" Or s = "^" Then Return True
Case 2
If s = "ln" Then Return True
Case 3
If s = "sin" Or s = "cos" Or s = "tan" Or s = "log" Then Return True
Case 4
If s = "ctan" Then Return True
Case Else
Return False
End Select
End Function
Private Sub fenjieKhtoJS(ByVal s As String)
'把一个字符串按括号进行分解,并计算结果
myJieGuo = ""
jieguoYN = ""
If canJiS(s) Then
Else
jieguoYN = "error,please check:括号不对"
myJieGuo = jieguoYN
Exit Sub
End If
If s.Substring(0, 1) = "-" Then '对于第一个字符为负号的字符串,进行转换
s = "0" & s
End If
Dim i As Integer
Dim khnum As Integer = 0
For i = 0 To s.Length - 1
If s.Substring(i, 1) = "(" Then khnum += 1
Next
Dim kk As String = "" '记录括号位置
If khnum = 0 Then '如果没括号
myJieGuo = myJS(s)
Else
ReDim mySubStr(khnum)
'MsgBox(khnum)
Dim myloopnum As Integer = 0
Dim s1 As String = s
Do While myloopnum < khnum '按括号数进行循环
myloopnum += 1
Dim ykhPo As Integer = 0 '右括号位置
Dim zkhPo As Integer = 0 '左括号位置
Dim ia As Integer = 0
Do While ykhPo = 0
ia += 1
If s.Substring(ia, 1) = ")" Then ykhPo = ia
Loop
For ia = ykhPo To 1 Step -1
If s.Substring(ia, 1) = "(" Then
zkhPo = ia
Exit For
End If
Next
mySubStr(myloopnum - 1) = s.Substring(zkhPo + 1, ykhPo - zkhPo - 1)
Dim AA As String
AA = myJS(mySubStr(myloopnum - 1))
s = s.Substring(0, zkhPo) & AA & s.Substring(ykhPo + 1, s.Length - 1 - ykhPo)
kk += Str(zkhPo) & Str(ykhPo) & vbCrLf & s & vbCrLf
Loop
End If
myJieGuo = myJS(s)
Dim ss As String = ""
For i = 0 To khnum - 1
ss += mySubStr(i) & vbCrLf
Next
If jieguoYN Is "" Then
Else
myJieGuo = jieguoYN
End If
' MsgBox("共有括号:" & Str(khnum) & vbCrLf & ss & vbCrLf & kk & vbCrLf)
End Sub
Private Function myJS(ByVal S As String) As String
'计算一个不带括号的字符串
Dim i As Integer = 0
Dim j As Integer = 0
Dim kk As Integer = 0
Dim k As String = ""
myJS = ""
If S = "" Then
myJS = "X"
''ElseIf S.Substring(0, 1) = "-" And (ynSZ(S.Substring(1, S.Length - 1)) = True) Then
''myJS = S
''ElseIf S.Substring(0, 1) = "-" Then
'' S = "0" & S
Else
fengeS(S)
If caozuofNum = 0 Then
myJS = jbJS(myVal(0))
Else
Dim cF2 As Integer = 0
Dim cF1 As Integer = 0
Dim cF As Integer = 0
For i = 0 To caozuofNum - 1 '分别取得 ^ 及 * 、/ 的数量
If myCaozuoF(i) = "^" Then cF2 += 1
If myCaozuoF(i) = "*" Or myCaozuoF(i) = "/" Then cF1 += 1
Next
cF = caozuofNum - cF1 - cF2
k += Str(cF2 + cF1) & vbCrLf & Str(caozuofNum) & vbCrLf
If cF2 = 0 Then
Else
For kk = 0 To cF2 - 1
For i = 0 To caozuofNum - 1
If myCaozuoF(i) = "^" Then
myVal(i) = yiCaozuoF(jbJS(myVal(i)), "^", jbJS(myVal(i + 1))).ToString
j = i
Do Until j >= caozuofNum - 1
j += 1
myVal(j) = myVal(j + 1)
myCaozuoF(j - 1) = myCaozuoF(j)
Loop
Exit For
End If
Next
Next
End If
If cF1 = 0 Then
Else
For kk = 0 To cF1 - 1
For i = 0 To caozuofNum - 1 - cF2
If myCaozuoF(i) = "*" Or myCaozuoF(i) = "/" Then
myVal(i) = yiCaozuoF(jbJS(myVal(i)), myCaozuoF(i), jbJS(myVal(i + 1))).ToString
j = i
Do Until j >= caozuofNum - 1
j += 1
myVal(j) = myVal(j + 1)
myCaozuoF(j - 1) = myCaozuoF(j)
Loop
Exit For
End If
Next
Next
End If
For kk = 0 To cF - 1
For i = 0 To caozuofNum - 1 - cF2 - cF1
If myCaozuoF(i) = "+" Or myCaozuoF(i) = "-" Then
myVal(i) = yiCaozuoF(jbJS(myVal(i)), myCaozuoF(i), jbJS(myVal(i + 1))).ToString
j = i
Do Until j >= caozuofNum - 1
j += 1
myVal(j) = myVal(j + 1)
myCaozuoF(j - 1) = myCaozuoF(j)
Loop
Exit For
End If
Next
Next
myJS = myVal(0)
For i = 0 To caozuofNum - 1
k += myVal(i) & vbCrLf & myCaozuoF(i) & vbCrLf
Next
k += myVal(caozuofNum)
' MsgBox(k)
End If
End If
Return myJS
End Function
Private Function yiCaozuoF(ByVal a As Double, ByVal f As String, ByVal b As Double) As Double
'+、-、*、/、^ 操作符的基本计算
Select Case f
Case "+"
yiCaozuoF = a + b
Case "-"
yiCaozuoF = a - b
Case "*"
yiCaozuoF = a * b
Case "/"
If b = 0 Then
jieguoYN = "error,please check! 除数为零了!!"
Else
yiCaozuoF = a / b
End If
Case "^"
If b < 1 And b > -1 And b <> 0 Then
If ((1 / b) Mod 2) <> 0 Then
If a < 0 Then
yiCaozuoF = -(-a) ^ b
Else
yiCaozuoF = a ^ b
End If
Else
If a < 0 Then
jieguoYN = "error,please check!幂的底数为负了"
Else
yiCaozuoF = a ^ b
End If
End If
Else
yiCaozuoF = a ^ b
End If
Case Else
yiCaozuoF = 0
End Select
Return yiCaozuoF
End Function
[解决办法]
感谢lz分享。