Expresiones

10/08/2005 - 23:02 por Demian | Informe spam
Hola, me surge una duda, quisiera evaluar una formula que tengo almacenada en
una base de datos, alguien sabe como hacer esto en tiempo de ejecucion??

Me explico un poco mas. En un campo de la base de datos tengo la siguiente
formula:
"x+y = 3"
"X" sera una variable en mi codigo asmismo lo sera "Y" y quisiera evaluar el
resultado de esta expresion, alguien conoce una clase que sirva para evaluar
expresiones o algo asi???

Gracias y saludos
 

Leer las respuestas

#1 Pedro M.Ferrando Moya
10/08/2005 - 23:55 | Informe spam
Implementé una clase hace poco a partir de unos apuntes en java de mi
sobrino, ahí va eso:



Imports System.Collections

Public Class Evaluator

Private Const EOL As Integer = 0
Private Const VALUE As Integer = 1
Private Const OPAREN As Integer = 2
Private Const CPAREN As Integer = 3
Private Const EXP As Integer = 4
Private Const MULT As Integer = 5
Private Const DIV As Integer = 6
Private Const PLUS As Integer = 7
Private Const MINUS As Integer = 8

Private Structure Precedence
Public inputSymbol As Integer
Public topOfStack As Integer

Sub New(ByVal inSymbol As Integer, ByVal topSymbol As Integer)
inputSymbol = inSymbol
topOfStack = topSymbol
End Sub
End Structure

Private Shared precTable() As Precedence = {New Precedence(0, -1), _
New Precedence(0, 0), _
New Precedence(100, 0), _
New Precedence(0, 99), _
New Precedence(6, 5), _
New Precedence(3, 4), _
New Precedence(3, 4), _
New Precedence(1, 2), _
New Precedence(1, 2)}


Private Class Token

Private m_type As Integer = EOL
Private m_value As Long = 0


Sub New(ByVal t As Integer, ByVal v As Long)
m_type = t
m_value = v
End Sub

Sub New(ByVal t As Integer)
Me.New(t, 0)
End Sub

Sub New()
Me.New(EOL)
End Sub

Public ReadOnly Property Type() As Integer
Get
Return m_type
End Get
End Property

Public ReadOnly Property Value() As Long
Get
Return m_value
End Get
End Property

End Class



Private Class stringTokenizer

Private m_alTokens As ArrayList
Private m_iIndex As Integer

Sub New(ByVal ai_sExpression As String, ByVal ai_sDelimiter As String)
m_alTokens = New ArrayList
Dim aStr() As String =
ai_sExpression.Split(ai_sDelimiter.ToCharArray)

Dim iPos As Integer = 0
For iCount As Integer = 0 To aStr.Length - 2
Dim s = aStr(iCount)
m_alTokens.Add(s)
iPos += s.Length
m_alTokens.Add(ai_sExpression.Substring(iPos, 1))
iPos += 1
Next
m_alTokens.Add(aStr(aStr.Length - 1))
m_iIndex = 0
End Sub

Public Function nextToken() As String
Dim sReturn As String
sReturn = m_alTokens(m_iIndex)
m_iIndex += 1
Return sReturn
End Function

Public Function hasMoreTokens() As Boolean
Return (m_iIndex < m_alTokens.Count)
End Function

End Class



Private Class EvalTokenizer

Private str As stringTokenizer

Sub New(ByVal m_oStr As stringTokenizer)
str = m_oStr
End Sub

Public Function getToken() As Token

Dim theValue As Long

If Not str.hasMoreTokens() Then
Return New Token
End If


Dim s As String = str.nextToken()
If (s.Equals("")) Then Return getToken()
If (s.Equals(" ")) Then Return getToken()
If (s.Equals("^")) Then Return New Token(EXP)
If (s.Equals("/")) Then Return New Token(DIV)
If (s.Equals("*")) Then Return New Token(MULT)
If (s.Equals("(")) Then Return New Token(OPAREN)
If (s.Equals(")")) Then Return New Token(CPAREN)
If (s.Equals("+")) Then Return New Token(PLUS)
If (s.Equals("-")) Then Return New Token(MINUS)

Try
theValue = CLng(s)
Catch e As Exception
Return New Token
End Try

Return New Token(VALUE, theValue)


End Function

End Class

Dim opStack As Stack
Dim postfixStack As Stack
Dim str As stringTokenizer


Sub New(ByVal s As String)

opStack = New Stack
postfixStack = New Stack

str = New stringTokenizer(s, "+*-/^()")
opStack.Push(EOL)


End Sub


Public Function getValue() As Long

Dim tok As EvalTokenizer = New EvalTokenizer(str)
Dim lastToken As Token


Do
lastToken = tok.getToken
processToken(lastToken)
Loop While lastToken.Type <> EOL



If (postfixStack.Count = 0) Then
Return 0
End If

Dim theResult As Long = postfixStack.Pop()


Return theResult


End Function


Private Sub processToken(ByVal lastToken As Token)


Dim topOp As Integer
Dim lastType As Integer = lastToken.Type


Select Case (lastType)

Case VALUE
postfixStack.Push(lastToken.Value)
Return

Case CPAREN
topOp = opStack.Peek()
While (topOp <> OPAREN And topOp <> EOL)
binaryOp(topOp)
topOp = opStack.Peek()
End While

If (topOp = OPAREN) Then
opStack.Pop()
Else
'error
End If



Case Else
topOp = opStack.Peek()
While (precTable(lastType).inputSymbol <=
precTable(topOp).topOfStack)
binaryOp(topOp)
topOp = opStack.Peek()
End While



If lastType <> EOL Then
opStack.Push(lastType)
End If

End Select


End Sub


Private Function postfixPop() As Long

If (postfixStack.Count = 0) Then
Return 0
End If

Return postfixStack.Pop()

End Function

Private Sub binaryOp(ByVal topOp As Integer)


If (topOp = OPAREN) Then
opStack.Pop()
Return
End If
Dim rhs As Long = postfixPop()
Dim lhs As Long = postfixPop()

If (topOp = EXP) Then
postfixStack.Push(Math.Pow(lhs, rhs))
ElseIf (topOp = PLUS) Then
postfixStack.Push(lhs + rhs)
ElseIf (topOp = MINUS) Then
postfixStack.Push(lhs - rhs)
ElseIf (topOp = MULT) Then
postfixStack.Push(lhs * rhs)
ElseIf (topOp = DIV) Then
If (rhs <> 0) Then
postfixStack.Push(lhs / rhs)
Else
postfixStack.Push(lhs) ' div por cero
End If
End If

opStack.Pop()

End Sub


End Class


y la llamas así, por ejemplo:

Dim ev As New Evaluator(TextBox1.Text)
MsgBox(ev.getValue)



"Demian" escribió:

Hola, me surge una duda, quisiera evaluar una formula que tengo almacenada en
una base de datos, alguien sabe como hacer esto en tiempo de ejecucion??

Me explico un poco mas. En un campo de la base de datos tengo la siguiente
formula:
"x+y = 3"
"X" sera una variable en mi codigo asmismo lo sera "Y" y quisiera evaluar el
resultado de esta expresion, alguien conoce una clase que sirva para evaluar
expresiones o algo asi???

Gracias y saludos

Preguntas similares