方法一: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
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。