Lo Logre!!!
Costo un poco.... lo hice ayer (domingo a la tarde jeje) y tenia un problema con los numeros negativos que hoy ya resolvi....aunque no he probado todo tipo de operaciones xD. Eso si....solo soporta los siguentes operadores: + * - / ( )
No soprota potenciación, ahora intentare agregarle esa funcion jeje
Como funciona?? (rapidamente explicado) Divide en terminos, si el termino es numerico suma o resta, si es una multiplicacion o division y/o con parentesis se analiza otra vez (usando recursividad).
No esta totalmente testeado, es MUY posible que encuentre algun error jeje, sigo trabajando en esta calcuComo usarlo?? Simple, llaman a Eval("5+3*9") por ejemplo y esta le retorna un valor double (en caso de que haya decimales)....
que no se diga mas..aca el codigo
Imports System.Text.RegularExpressions
Module Module1
Sub Main()
Dim opcion As String = ""
Console.WriteLine("Ingrese una operacion combinada o 'end' para salir")
Do
opcion = Console.ReadLine()
If opcion = "end" Then Exit Do
Try
Console.WriteLine("Resultado: " & Eval(opcion).ToString("N"))
Catch ex As Exception
Console.ForegroundColor = ConsoleColor.White
Console.WriteLine("Error: " & ex.Message)
Console.ForegroundColor = ConsoleColor.Gray
End Try
Loop
End Sub
Public Function Eval(ByVal operacion As String) As Double
Dim resp As Double = 0D
Dim temp As Double = 0D
operacion = operacion.Replace(" ", "")
operacion = operacion.Replace(".", ",")
Dim RegexObj As New Regex( _
"(?<Termino>[+\-]? (?: \d [\d,*/]* | \( [\d,+\-*/]* \) (?: [*/] \d | [*/] \( [\d,+\-*/]* \) )* ) )", _
RegexOptions.IgnorePatternWhitespace)
If RegexObj.IsMatch(operacion) Then
Dim MatchResults As MatchCollection = RegexObj.Matches(operacion)
Dim MatchResult As Match = MatchResults(0)
Dim termino As String
For i As Int32 = 0 To MatchResults.Count - 1
termino = MatchResult.Groups("Termino").Value
If IsNumeric(termino) Then
temp = Double.Parse(termino)
Else
' No podemos pasarle +(5+5)*2 porque lo tomaria como termino y entraria en un bucle infinito
' asi que le extraemos el signo, por defecto le ponemos como positivo y despues le volvemos al
' signo que debe tener
Dim signo As Integer = 1
If termino.Substring(0, 1) = "-" Then
signo = -1
termino = termino.Substring(1)
ElseIf termino.Substring(0, 1) = "+" Then
signo = 1
termino = termino.Substring(1)
End If
temp = ResolverTermino(termino)
temp *= signo ' Multiplicamos por -1 para cambiar el signo, por 1 para mantenerlo igual
End If
resp += temp
MatchResult = MatchResult.NextMatch()
Next
Return resp
Else
Throw New Exception("La operacion no pudo ser reconocida")
End If
End Function
Function ResolverTermino(ByVal Termino As String) As Double
Dim resp As Double = 0D
Dim temp As Double = 0D
Dim RegexObj As New Regex("(?<Termino> [\+\-]?\( .* \) | [\*\/] \d*\,?\d* | [\+\-]? \d*\,?\d* )", RegexOptions.IgnorePatternWhitespace)
If RegexObj.IsMatch(Termino) Then
Dim MatchResults As MatchCollection = RegexObj.Matches(Termino)
Dim MatchResult As Match = MatchResults(0)
Dim subTermino As String
For I As Int32 = 0 To MatchResults.Count - 2
subTermino = MatchResult.Groups("Termino").Value
If IsNumeric(subTermino) Then
resp = Double.Parse(subTermino)
Else
Select Case subTermino.Substring(0, 1)
Case "*"
temp = Double.Parse(subTermino.Substring(1))
resp *= temp
Case "/"
temp = Double.Parse(subTermino.Substring(1))
resp /= temp
Case Else
resp = Eval(Regex.Match(subTermino, "\((?<Operacion>.*)\)").Groups("Operacion").Value)
End Select
End If
MatchResult = MatchResult.NextMatch
Next
Return resp
Else
Throw New Exception("Parte de la operacion no pudo ser reconocida")
End If
End Function
End Module
Esta en vb.net.....pero es facilmente convertible, cuando este bien terminado y sin bugs (por ejemplo, ahora no se puede poner "((1+2)*3)*4)" porque lo rompes jajaja) lo convertire a C# con mis propias manos xD
Cualquier ayuda se agradece
EDIT: Arreglado el tema de los espacios, y el punto (que es una coma en realidad)