方法一:DataColumn.Expression & DataTable.Compute方法(不支持函数)
DataColumn.Expression:
Dim objData As New DataTable
objData.Columns.Add("a", Type.GetType(Integer))
objData.Columns.Add("b", Type.GetType(Integer))
objData.Columns.Add("c", Type.GetType(Integer))
Dim objCol As DataColumn = _
objData.Columns.Add("x", Type.GetType(Integer))
objCol.Expression = "a+b*c-2"
Dim objRow As DataRow = DataTable.NewRow()
objRow("a") = 2
objRow("b") = 3
objRow("c") = 4
objData.Rows.Add(objRow)
Console.WriteLine(objData.Rows(0)("x"))
DataTable.Compute:
MessageBox.Show((new DataTable()).Compute("1+2*3/4", "").ToString())
方法二:SQL的方式
方法三:解析
Imports System.Text.RegularExpressions
Public Class Evaluate
Shared ReadOnly m_instance As New Evaluate()
''' <summary>
''' 构造函数
''' </summary>
''' <remarks></remarks>
Shared Sub New()
End Sub
''' <summary>
''' 获取实例
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Shared ReadOnly Property Instance() As Evaluate
Get
Return m_instance
End Get
End Property
' A number is a sequence of digits optionally followed by a dot and
' another sequence of digits. The number in parenthesis in order to
' define an unnamed group.
Private Const Num As String = "(\-?\d+\.?\d*)"
' List of 1-operand functions.
Private Const Func1 As String = "(exp|log|log10|abs|sqr|sqrt|sin|cos|tan|asin|acos|atan)"
' List of 2-operand functions.
Private Const Func2 As String = "(atan2)"
' List of N-operand functions.
Private Const FuncN As String = "(min|max)"
' List of predefined constants.
Private Const Constants As String = "(e|pi)"
Function Eval(ByVal expr As String) As Double
' Define one Regex object for each supported operation.
' They are outside the loop, so that they are compiled only once.
' Binary operations are defined as two numbers with a symbol between them
' optionally separated by spaces.
Dim rePower As New Regex(Num & "\s*(\^)\s*" & Num)
Dim reAddSub As New Regex(Num & "\s*([-+])\s*" & Num)
Dim reMulDiv As New Regex(Num & "\s*([*/])\s*" & Num)
' These Regex objects resolve call to functions. (Case insensitivity.)
Dim reFunc1 As New Regex(Func1 & "\(\s*" & Num & "\s*\)", _
RegexOptions.IgnoreCase)
Dim reFunc2 As New Regex(Func2 & "\(\s*" & Num & "\s*,\s*" & Num _
& "\s*\)", RegexOptions.IgnoreCase)
Dim reFuncN As New Regex(FuncN & "\((\s*" & Num & "\s*,)+\s*" & Num _
& "\s*\)", RegexOptions.IgnoreCase)
' This Regex object drop a + when it follows an operator.
Dim reSign1 As New Regex("([-+/*^])\s*\+")
' This Regex object converts a double minus into a plus.
Dim reSign2 As New Regex("\-\s*\-")
' This Regex object drops parenthesis around a number.
' (must not be preceded by an alphanum char (it might be a function name)
Dim rePar As New Regex("(?<![A-Za-z0-9])\(\s*([-+]?\d+.?\d*)\s*\)")
' A Regex object that tells that the entire expression is a number
Dim reNum As New Regex("^\s*[-+]?\d+\.?\d*\s*$")
' The Regex object deals with constants. (Requires case insensitivity.)
Dim reConst As New Regex("\s*" & Constants & "\s*", _
RegexOptions.IgnoreCase)
' This resolves predefined constants. (Can be kept out of the loop.)
expr = reConst.Replace(expr, AddressOf DoConstants)
' Loop until the entire expression becomes just a number.
Do Until reNum.IsMatch(expr)
Dim saveExpr As String = expr
' Perform all the math operations in the source string.
' starting with operands with higher operands.
' Note that we continue to perform each operation until there are
' no matches, because we must account for expressions like (12*34*56)
' Perform all power operations.
Do While rePower.IsMatch(expr)
expr = rePower.Replace(expr, AddressOf DoPower)
Loop
' Perform all divisions and multiplications.
Do While reMulDiv.IsMatch(expr)
expr = reMulDiv.Replace(expr, AddressOf DoMulDiv)
Loop
' Perform functions with variable numbers of arguments.
Do While reFuncN.IsMatch(expr)
expr = reFuncN.Replace(expr, AddressOf DoFuncN)
Loop
' Perform functions with 2 arguments.
Do While reFunc2.IsMatch(expr)
expr = reFunc2.Replace(expr, AddressOf DoFunc2)
Loop
' 1-operand functions must be processed last to deal correctly with
' expressions such as SIN(ATAN(1)) before we drop parenthesis
' pairs around numbers.
Do While reFunc1.IsMatch(expr)
expr = reFunc1.Replace(expr, AddressOf DoFunc1)
Loop
' Discard + symbols (unary pluses)that follow another operator.
expr = reSign1.Replace(expr, "$1")
' Simplify 2 consecutive minus signs into a plus sign.
expr = reSign2.Replace(expr, "+")
' Perform all additions and subtractions.
Do While reAddSub.IsMatch(expr)
expr = reAddSub.Replace(expr, AddressOf DoAddSub)
Loop
' attempt to discard parenthesis around numbers. We can do this
expr = rePar.Replace(expr, "$1")
' if the expression didn't change, we have a syntax error.
' this serves to avoid endless loops
If expr = saveExpr Then
' if it didn't work, exit with syntax error exception.
Throw New Data.SyntaxErrorException()
Return 0
End If
Loop
' Return the expression, which is now a number.
Return CDbl(expr)
End Function
' These functions evaluate the actual math operations.
' In all cases the Match object on entry has groups that identify
' the two operands and the operator.
Function DoConstants(ByVal m As Match) As String
Select Case m.Groups(1).Value.ToUpper
Case "PI"
Return Math.PI.ToString
Case "E"
Return Math.E.ToString
End Select
Return "0"
End Function
Function DoPower(ByVal m As Match) As String
Dim n1 As Double = CDbl(m.Groups(1).Value)
Dim n2 As Double = CDbl(m.Groups(3).Value)
' Group(2) is always the ^ character in this version.
Return (n1 ^ n2).ToString
End Function
Function DoMulDiv(ByVal m As Match) As String
Dim n1 As Double = CDbl(m.Groups(1).Value)
Dim n2 As Double = CDbl(m.Groups(3).Value)
Dim str As String = ""
Select Case m.Groups(2).Value
Case "/"
str = (n1 / n2).ToString
Case "*"
str = (n1 * n2).ToString
End Select
Return str
End Function
Function DoAddSub(ByVal m As Match) As String
Dim n1 As Double = CDbl(m.Groups(1).Value)
Dim n2 As Double = CDbl(m.Groups(3).Value)
Dim str As String = ""
Select Case m.Groups(2).Value
Case "+"
str = (n1 + n2).ToString
Case "-"
str = (n1 - n2).ToString
End Select
Return str
End Function
' These functions evaluate functions.
Function DoFunc1(ByVal m As Match) As String
' function argument is 2nd group.
Dim n1 As Double = CDbl(m.Groups(2).Value)
Dim str As String = ""
' function name is 1st group.
Select Case m.Groups(1).Value.ToUpper
Case "EXP"
str = Math.Exp(n1).ToString
Case "LOG"
str = Math.Log(n1).ToString
Case "LOG10"
str = Math.Log10(n1).ToString
Case "ABS"
str = Math.Abs(n1).ToString
Case "SQR", "SQRT"
str = Math.Sqrt(n1).ToString
Case "SIN"
str = Math.Sin(n1).ToString
Case "COS"
str = Math.Cos(n1).ToString
Case "TAN"
str = Math.Tan(n1).ToString
Case "ASIN"
str = Math.Asin(n1).ToString
Case "ACOS"
str = Math.Acos(n1).ToString
Case "ATAN"
str = Math.Atan(n1).ToString
End Select
Return str
End Function
Function DoFunc2(ByVal m As Match) As String
' function arguments are 2nd and 3rd group.
Dim n1 As Double = CDbl(m.Groups(2).Value)
Dim n2 As Double = CDbl(m.Groups(3).Value)
Dim str As String = ""
' function name is 1st group.
Select Case m.Groups(1).Value.ToUpper
Case "ATAN2"
str = Math.Atan2(n1, n2).ToString
End Select
Return str
End Function
Function DoFuncN(ByVal m As Match) As String
' function arguments are from group 2 onward.
Dim args As New ArrayList()
Dim i As Integer = 2
' Load all the arguments into the array.
Do While m.Groups(i).Value <> ""
' Get the argument, replace any comma to space, and convert to double.
args.Add(CDbl(m.Groups(i).Value.Replace(","c, " "c)))
i += 1
Loop
Dim str As String = ""
' function name is 1st group.
Select Case m.Groups(1).Value.ToUpper
Case "MIN"
args.Sort()
str = args(0).ToString
Case "MAX"
args.Sort()
str = args(args.Count - 1).ToString
End Select
Return str
End Function
End Class
方法四:
http://www.codeproject.com/vb/net/expression_evaluator.asp
参考资料:http://blog.csdn.net/fangxinggood/article/details/5992661
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。