es una calculadora basica lo unico que hace es operaciones por jerarquia como las calculadoras de mano donde primero resuelve las operaciones dentro de los parentesis en su orden de jerarquia */+- y asi va destruyendo parentesis hasta desmenusar todo lo digitado, para mayor funcionalidad lee toda la expresion de una vez.
orden primero las multiplciaiciones y diviciones y luego las sumas y las resta
(http://img444.imageshack.us/img444/8669/35913399.jpg)
(http://img41.imageshack.us/img41/3333/39382216.jpg)
codigo
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace comienzo
{
class parte3
{
public void imprimir(string [] operacion)
{
/*Console.Clear();
byte posx = 5;
for (int i = 0; i <= 19; i++)
{
Console.SetCursorPosition(posx, 6); Console.WriteLine(operacion[i]);
posx += 1;
}*/
Console.SetCursorPosition(18,6); Console.WriteLine("Resultado = " + operacion[1]);
Console.ReadKey();
}///fin public void imprimir
}
class partedos
{
public void buscaresp(byte pcdo, byte pato, string[] operacion)///busca los espacion dentro del parentesis
{
string cambio;
pcdo -= 2;
for (; pato <= pcdo; pato++) ////for 1-3
{
if (operacion[pato] == " ")////if 1-3
{
pato += 2;
cambio = operacion[pato];
pato -= 2;
operacion[pato] = cambio;
pato += 2;
operacion[pato] = " ";
pato -= 2;
}///fin if 1-3
}////fin for 1-3
//Console.WriteLine(operacion[2]);
}///fin buscaresp
public void organiza(byte pcdo, byte pato, string[] operacion)////organiza toda la expresion quitando los espacios en blanco
{
byte ultimo = 0; string cambio; byte posb =0;
pcdo = 19;
while (pcdo >= 1)
{
ultimo = pcdo;
while (ultimo >= 1)
{
posb = Convert.ToByte(ultimo - 1);
if (posb != 255)
{
while ( ((posb != 255) &&(posb >= 0) ) && (operacion[posb] == " ") )
{
cambio = operacion[ultimo];
operacion[posb] = cambio;
operacion[ultimo] = " ";
posb--;
}///fin while que bsuca las posiciones vacias
}
ultimo--;
}///fin while que busca desde el ultimo
pcdo--;
}///fin pcdo
// Console.WriteLine(operacion[2]);
}///fin opublic void organiza
public void parentesis (string [] operacion, byte pfin)
{
byte abierto = 0, pcdo = 0, pato = 0,a,b,k,contar; ///k revisa la operacion antes del aprentesis
double x=0, y=0, resultado=0;
partedos organizar = new partedos();
partedos acomodar = new partedos();
while(abierto==0)///while1---crear un siclo que busque lso parentesis si no los hay coloca el abierto en 0
{
for (byte i = 0; i <=pfin ; i++)///for que recorre////cambiar por un while
{
if ( (operacion[i] == "(") )//if-1
{
pato = i; pcdo = i; pcdo += 1;
while( (operacion[pcdo] !="(") && (operacion[pcdo]!=")"))//while que busca la termiancion dle aprentesis
{
pcdo += 1;
}///fin while que bsuca la termiancion del aprentesis
if (operacion[pcdo] != "(")
{
byte j=Convert.ToByte (pato + 1);
for (; j <= pcdo;j++ )///for-2 como primeor se realizan las * & / hago este for
{
if (operacion[j] == "*")//if-2
{
a = j; b = j;
a -= 1; b += 1;
x = Convert.ToDouble(operacion[a]); y = Convert.ToDouble(operacion[b]);
resultado = x * y;
//// ahora escribo el resultado en la posicion anteriro al asterisco
//// & borro las otras dos posiciones /**/
/**/ a = j; b = j; /**/
/**/ a -= 1; b += 1; /**/
/**/ operacion[a] = Convert.ToString(resultado); /**/
/**/ operacion[j] = " "; operacion[b] = " "; /**/
////////////////////////////////////////////////////////////////
j = a;
organizar.buscaresp(pcdo, pato, operacion);
acomodar.organiza(pcdo, pato, operacion);
pcdo -= 2;
}//fin if-2
else
{
if (operacion[j] == "/")//if-3
{
a = j; b = j;
a -= 1; b += 1;
x = Convert.ToDouble(operacion[a]); y = Convert.ToDouble(operacion[b]);
resultado = x / y;
//// ahora escribo el resultado en la posicion anteriro al asterisco
//// & borro las otras dos posiciones /**/
/**/ a = j; b = j; /**/
/**/ a -= 1; b += 1; /**/
/**/ operacion[a] = Convert.ToString(resultado); /**/
/**/ operacion[j] = " "; operacion[b] = " "; /**/
////////////////////////////////////////////////////////////////
j = a;
organizar.buscaresp(pcdo, pato, operacion);
acomodar.organiza(pcdo, pato, operacion);
pcdo -= 2;
}//fin if-3
}///fin else que em conduce a la divicion
}///fin for-2
///
////////////////operaciones segundarias
j = Convert.ToByte(pato + 1);
for (; j <= pcdo; j++)///for-3 con este for realizo las operaciones segundarias
{
if (operacion[j] == "+")//if-4
{
a = j; b = j;
a -= 1; b += 1;
x = Convert.ToDouble(operacion[a]); y = Convert.ToDouble(operacion[b]);
resultado = x + y;
//// ahora escribo el resultado en la posicion anteriro al asterisco
//// & borro las otras dos posiciones /**/
/**/ a = j; b = j;
/**/ a -= 1; b += 1; /**/
/**/ operacion[a] = Convert.ToString(resultado); /**/
/**/ operacion[j] = " "; operacion[b] = " "; /**/
////////////////////////////////////////////////////////////////
j = a;
organizar.buscaresp(pcdo, pato, operacion);
acomodar.organiza(pcdo, pato, operacion);
pcdo -= 2;
}//fin if-4
else
{
if (operacion[j] == "-")//if-5
{
a = j; b = j;
a -= 1; b += 1;
x = Convert.ToDouble(operacion[a]); y = Convert.ToDouble(operacion[b]);
resultado = x - y;
//// ahora escribo el resultado en la posicion anteriro al asterisco
//// & borro las otras dos posiciones /**/
/**/ a = j; b = j; /**/
/**/ a -= 1; b += 1; /**/
/**/ operacion[a] = Convert.ToString(resultado); /**/
/**/ operacion[j] = " "; operacion[b] = " "; /**/
////////////////////////////////////////////////////////////////
j = a;
organizar.buscaresp(pcdo, pato, operacion);
acomodar.organiza(pcdo, pato, operacion);
pcdo -= 2;
}//fin if-5
}///fin else que em conduce a la divicion
}///fin for-2
///
///////////////fin for-3
if (pato >= 1)
{
k = Convert.ToByte(pato - 1);
if (operacion[k] == "+" || operacion[k] == "(" || operacion[k] == ")" || operacion[k] == "-" || operacion[k] == "*" || operacion[k] == "/")
{
operacion[pato] = " "; operacion[pcdo] = " ";
acomodar.organiza(pcdo, pato, operacion);
}
else
{
operacion[pato] = "*"; operacion[pcdo] = " ";
acomodar.organiza(pcdo, pato, operacion);
}
}///fin pto>=1
//Console.SetCursorPosition(15, 12); Console.WriteLine(operacion[0]);
contar=0;
for (int z = 0; z <= 19; z++)///for que busca haber cuantos parentesis hay
{
if (operacion[z] == "(")
{
contar++;
}
}///fin for que busca haber cuantos parentesis hay
if (contar == 1) abierto = 1;
}///fin si del parentesis != abierto
///
///como termino las operaciones dentro de los parentesis los borro
}///fin if-1
}///fin for que recorre
}///fin while1
}///fin public void parentesis
}///fin class partedos
class parteuno
{
static void Main(string[] args)
{
Console.Title = ("calculadora jerarquica----Clipto");
string [] operacion = new string[23];
byte pos = 1,pfin=0;
string temp1,temp2=" ";
partedos enviar = new partedos();
parte3 final = new parte3();
operacion[0] = "("; operacion[19] = ")";
do
{
temp1 = Convert.ToString(Console.ReadKey().KeyChar);
if (temp1 != "\r")
{
if (temp2 == " ")
{
if (temp1 == "+" || temp1 == "(" || temp1 == ")" || temp1 == "-" || temp1 == "*" || temp1 == "/")
{
operacion[pos] = temp1;
pos++;
}
else
{
operacion[pos] = operacion[pos] + temp1;
}
}///fin temp2==" "
else
{
if (temp1 == "+" || temp1 == "(" || temp1 == ")" || temp1 == "-" || temp1 == "*" || temp1 == "/")
{
if (temp2 == "+" || temp2 == "(" || temp2 == ")" || temp2 == "-" || temp2 == "*" || temp2 == "/")
{
operacion[pos] = temp1;
pos++;
}
else
{
pos++; operacion[pos] = temp1; pos++;
}
}
else
{
operacion[pos] = operacion[pos] + temp1;
}
}//fin else de temp2==" "
}///fin temp1 != /r
else
{
pfin = pos;
}
temp2 = Convert.ToString(Console.ReadKey().KeyChar);
if (temp2 != "\r")
{
if (temp2 == "+" || temp2 == "(" || temp2 == ")" || temp2 == "-" || temp2 == "*" || temp2 == "/")
{
if (temp1 == "+" || temp1 == "(" || temp1 == ")" || temp1 == "-" || temp1 == "*" || temp1 == "/")
{
operacion[pos] = temp2;
pos++;
}
else
{
pos++; operacion[pos] = temp2; pos++;
}
}
else
{
operacion[pos] = operacion[pos] + temp2;
}
}///fin temp2 != /r
else
{
pfin = pos;
}
} while ((pos < 19) && (temp1 != "\r") && (temp2 != "\r"));
/* Console.SetCursorPosition(2, 4);Console.WriteLine(" ------ ");
for (int i = 0; i <= 9; i++)
{
Console.WriteLine(operacion[i]);
}*/
enviar.parentesis(operacion,pfin);
final.imprimir(operacion);
Console.Clear();
byte posx = 5;
for (int m = 0; m <= 19; m++)
{
Console.SetCursorPosition(posx, 6); Console.WriteLine(operacion[m]);
posx += 1;
}
//Console.ReadKey();
}///fin main
}///fin class
}///fin namespace
Nota: para hacerlo ultilice vectores no se me ocurrio +nada, si alguien sabe de otro metodo me comenta
Interesante.
¿Sabes ahcerlo en modo Visual?
Saludo.
:D :D ;-) ;-)
interesante, justo tenia que armarme una de estas, pero no que resuelva, sino que simplemente devuelva variables boleanas. (Seria como comprobar la formula SI de excel, solo que en lugar de celdas, hay variables ;D)
Cita de: Meta en 30 Julio 2009, 15:46 PM
Interesante.
¿Sabes ahcerlo en modo Visual?
Saludo.
es casi lo mismo si le colocas un modo grafico seria tener unos botones como los que tiene la calc de windows u otra, y lo que vas ahcer es que en partes como
Citartemp1 = Convert.ToString(Console.ReadKey().KeyChar);
dices que temp1 es igual ala tecla a la cual se le hizo click asi mismo sera con temp2 solo tienes que organizar eso, y como maneja vectores el proceso seria el mismo osea se deja igual, para el resultado o las partes donde imprime ejemplo
CitarConsole.SetCursorPosition(18,6); Console.WriteLine("Resultado = " + operacion[1]);
Console.ReadKey();
dises que limpie la caja de texto y que coloque ahi el resultado solamente
Para hacerlo en modo visual, no bastaría con leer el contenido en una caja de texto?
Cita de: Seu¥ en 31 Julio 2009, 00:57 AM
Para hacerlo en modo visual, no bastaría con leer el contenido en una caja de texto?
no porque el codigo va leyendo cada caracter que se ingresa y va armando la esctructura (o al menos eso veo a simple vista, no lo probe ni lo vi bien todavia, es dificil ver e imaginar exactamente como funciona el codigo estando en blanco y negro xD xD). el "do" que esta en el void Main se tendria que poner en otro bucle que vaya recorriendo letra x letra de un textbox (aunque es algo arreglado con alambres xD, lo mejor seria rehacer eso en una clase utilzable, aunque seria mas costoso creo :P)
pues tambien lo podrias hacer, lo que hace este en modo consola es que cada cosa que se digite la guarde en una posicion de un vector, para asi trabajar en segundo plano y empezar a resolver desde el parentesis mas interno al mas externo teniendo en cuenta la jerarquia de signos */+-, por eso le plante a Meta qeu podia hacerlo asi y no tenia que hacer tantas modificaciones del codigo fuente
Cita de: raul338 en 31 Julio 2009, 01:20 AM
Cita de: Seu¥ en 31 Julio 2009, 00:57 AM
Para hacerlo en modo visual, no bastaría con leer el contenido en una caja de texto?
no porque el codigo va leyendo cada caracter que se ingresa y va armando la esctructura (o al menos eso veo a simple vista, no lo probe ni lo vi bien todavia, es dificil ver e imaginar exactamente como funciona el codigo estando en blanco y negro xD xD). el "do" que esta en el void Main se tendria que poner en otro bucle que vaya recorriendo letra x letra de un textbox (aunque es algo arreglado con alambres xD, lo mejor seria rehacer eso en una clase utilzable, aunque seria mas costoso creo :P)
:O Disculpa, no he visto el código.
:S Primera vez que oigo un método así. ¿No sería mejor colocar toda la expresión ingresada, en "stack" y luego ir analizando?
no se, la verdad primera ves que escucho de stack solo soy un newbie y vi este reto en un foro donde se debia hacer esta calculadora desde cero con las cosas basicas que uno conoce sin ultilizar funciones del lenguaje donde se trabaje & quise hacerlo con las cosas basicas que conocia, pero te propongo que plantees el metodo para analizarlo, y ver como funciona por dentro, y tratar de generar uno igual.
depende a que te refieres con "stack" (la clase generica? o a la memoria en si xD, como "heap") si es en la clase, si seria lo mismo a la alternativa que mencione yo.
Cita de: clipto en 31 Julio 2009, 01:39 AM
no se, la verdad primera ves que escucho de stack solo soy un newbie y vi este reto en un foro donde se debia hacer esta calculadora desde cero con las cosas basicas que uno conoce sin ultilizar funciones del lenguaje donde se trabaje & quise hacerlo con las cosas basicas que conocia, pero te propongo que plantees el metodo para analizarlo, y ver como funciona por dentro, y tratar de generar uno igual.
es un reto??? xD yo tengo que hacer uno igual, este me sirve a medias :P (sin ofender, pero no es lo que busco). A mi se me ocurrio usar expresiones regulares, pero seria muuuy larga la expresion, asi que probare. Igual posteare el codigo
CitarUna pila (stack en inglés) es una lista ordinal o estructura de datos en la que el modo de acceso a sus elementos es de tipo LIFO (del inglés Last In First Out, último en entrar, primero en salir) que permite almacenar y recuperar datos. Se aplica en multitud de ocasiones en informática debido a su simplicidad y ordenación implícita en la propia estructura.
Representación gráfica de una pila
Para el manejo de los datos se cuenta con dos operaciones básicas: apilar (push), que coloca un objeto en la pila, y su operación inversa, retirar (o desapilar, pop), que retira el último elemento apilado.
A eso me refería.
Citares un reto??? xD
Yo también lo vi de esa manera.
Este tema, lo había analizado en VB, y cobein me recomendó lo de la pila.
Un saludo!
Cita de: Seu¥ en 31 Julio 2009, 01:46 AM
CitarUna pila (stack en inglés) es una lista ordinal o estructura de datos en la que el modo de acceso a sus elementos es de tipo LIFO (del inglés Last In First Out, último en entrar, primero en salir) que permite almacenar y recuperar datos. Se aplica en multitud de ocasiones en informática debido a su simplicidad y ordenación implícita en la propia estructura.
Representación gráfica de una pila
Para el manejo de los datos se cuenta con dos operaciones básicas: apilar (push), que coloca un objeto en la pila, y su operación inversa, retirar (o desapilar, pop), que retira el último elemento apilado.
A eso me refería.
Entonces si, es la clase generica xD
Cita de: Seu¥ en 31 Julio 2009, 01:46 AM
Citares un reto??? xD
Yo también lo vi de esa manera.
Este tema, lo había analizado en VB, y cobein me recomendó lo de la pila.
Un saludo!
Yo tengo que hacerlo en vb.net (que es en donde lo necesito para el proyecto que estoy haciendo). Pensaba hacerlo de esta manera
1- Dividir por terminos (a travez de una o tres expresiones regulares) dividir llaves, corchetes, parentesis; multiplicacion y division; suma y resta
2 - Analizar las ecuaciones ( yo lo necesito, pero no ecuaciones con X, sino con palabras claves, ej: A200 seria un valor que ya tengo en una tabla)
3 - Resolver la ecuacion mas "baja" (la que se debe resolver primero xD) y de ahi ir subiendo...
se entiende??? xD despues planteo codigo
CitarDividir por terminos (a travez de una o tres expresiones regulares) dividir llaves, corchetes, parentesis; multiplicacion y division; suma y resta
Exacto, solo hace falta saber matemáticas. Comienzas a recorrer la pila, ten en cuenta que el primero es el último, {} luego [] () ... / * ... + y - , y mientras recorres lo resuelves.
Ahora con respecto a lo de ecucaciones, si unicamente son valores que están en una tabla, no es muy difícil, si en realidad son ecuaciones, tendrás que recurrir a métodos para averigurar la complejidad de dicha ecucación y utilizar algún método de algebra avanzada para hacer eficiente tu programa, hace un tiempo hice un programa en Pascal para resolver ecuaciones por el método de Gauss, pero luego perdí el código.
Un saludo!
Cita de: Seu¥ en 31 Julio 2009, 01:58 AM
CitarDividir por terminos (a travez de una o tres expresiones regulares) dividir llaves, corchetes, parentesis; multiplicacion y division; suma y resta
Exacto, solo hace falta saber matemáticas. Comienzas a recorrer la pila, ten en cuenta que el primero es el último, {} luego [] () ... / * ... + y - , y mientras recorres lo resuelves.
No entiendo como lo harias con una pila :-\
Una pila, es simplemente una lista o array.
Es como si tendrías esto:
{'(','1','+','3',')'};
El primer dato a analizar será ')'.
Espero no estar equivocado.
Cita de: Seu¥ en 31 Julio 2009, 02:36 AM
Una pila, es simplemente una lista o array.
Es como si tendrías esto:
{'(','1','+','3',')'};
El primer dato a analizar será ')'.
Espero no estar equivocado.
estas bien, y si eso lo se, pero no entiendo la logica de analizar una pila xD
Que en la pila no tendrás una limitación de compilación, sino la tendrás cuando estés dentro del programa; por algo es una ventaja del programador trabajar con memoria dinámica. No se trata de lógica, sino de aprovechar los recursos de una pc, es simplemente un "array dinámico".
pila, lista, cola, arboles etc, son lo mismo.
pila--> El ultimo elemento que entra es el primero en salir. Ejemplo
apliar(2);
apliar(3);
apliar(4);
en la pila tenemos 4-3-2
si quieremos mostrar los elementos de la pila mostraremos el 4 luego el 3 y luego el 2.
lista es lista y punto jaja
cola--> El ultumo que entra es el ultimo en salir (como en la cola del cine, por orden de entrada).
encolar(2);
encolar(3);
encolar(4);
en la cola la tenemos 2-3-4
si quieremos mostrar los elementos de la pila mostraremos el 4 luego el 3 y luego el 2.
Lo bueno de las pilas es que te permite usar recusividad muy facilmente. Al contrario que la cola.
un saludo!!º
Cita a wikipedia:
CitarEn programas de aplicación escrito en un lenguaje de alto nivel, una pila puede ser implementada de manera eficiente, ya sea usando vectores o listas enlazadas.
CitarExpresión de evaluación y análisis sintáctico sintaxis
Se calcula empleando la notación polaca inversa utilizando una estructura de pila para los posibles valores. Las expresiones pueden ser representadas en prefijo, infijo, postfijo. La conversión de una forma de la expresión a otra forma necesita de una pila. Muchos compiladores utilizan una pila para analizar la sintaxis de las expresiones, bloques de programa, etc. Antes de traducir el código de bajo nivel. La mayoría de los lenguajes de programación son de contexto libre de los idiomas que les permite ser analizados con máquinas basadas en la pila.
Por ejemplo, el cálculo: ((1 + 2) * 4) + 3, puede ser anotado como en notación postfija con la ventaja de no prevalecer las normas y los paréntesis necesarios:
1 2 + 4 * 3 +
La expresión es evaluada de izquierda a derecha utilizando una pila:
* Apilar cuando se enfrentan a un operando y
* Desafilar dos operandos y evaluar el valor cuando se enfrentan a una operación.
* Apilar el resultado.
Espero que eso aclare las dudas ;)
thedoctor77 se usar estructuras de datos.
Lo que no entendia la logica de las pilas. Pero hay un error jeje..... que pasa si yo meto para calcular 6 + (8 + 3) - [6 * (3 + 2) + 5] * (2 * 10 / 5) + (5 * ((2 * 6) + 2)
habria que ordenarlos, xq de la forma que emplea Seu¥ creo que no funcionaria porque no esta ordenada
bueno he estado pendiente de estos post porque me gustaria emplear las pilas (para casos como este u otros) pero buscando en internet encontre esto:
(http://img382.imageshack.us/img382/5113/pilas2.jpg)
pero mi duda consiste esque ese ejemplo muesta que toma desde el ultimo valor y va calculado, pero mi duda consiste enque ahi esta organizado pero en una cadena desorganizada por lo menos la siguiente:
((5*8)-2)+5-7
donde segun las pilas empesaria por el ultimo valor, pero por jerarquia deberia empezar por 5*8 desde los primeros valores hasta el ultimo; y expresiones mas complejas como la dicha por raul338
6 + (8 + 3) - [6 * (3 + 2) + 5] * (2 * 10 / 5) + (5 * ((2 * 6) + 2)
entonces ¿es necesario que esten organizadas las expresiones para que las pilas funcionen?
Creo que uno no siempre comienza con el último valor, ya que hay métodos en listas enlazadas para encontrar un elemento el cual "analizar" o en este caso, resolver.
Nuevamente,disculpas si me equivoco..
La ayudita de clipto me sirvio, y creo encontrar el error jeje.... y estuve pensando, estamos mal en no tomar en cuenta los parentesis como deberian ser tomados!!!!
Nosotros en matematicas que hacemos si vemos un parentesis, corchetes o llaves????
Primero resolvemos lo que esta dentro y despues continuamos. Asi que, en la pila podria quedar asi
6 + (8 + 3) - (6 * (3 + 2) + 5) * (2 * 10 / 5) + (5 * ((2 * 6) + 2)
Citar1: +6
2: (8 + 3)
3: - (6 * (3 + 2) + 5) * (2 * 10 / 5)
4: (5 * ((2 * 6) + 2)
luego, con un parser que estoy creando, deberia crearse
otra pila, asi
Citar1: +6
2: // Una pila dentro de otra pila, medio lioso, pero asi se me ocurrio xD
2.1: +8
2.2: +3
3:
3.1: +6 * (3 + 2) + 5
3.2: *+(2 * 10 / 5)
4:
4.1: +5 * (2 * 6)
4.2: +2
3º vuelta:
Citar1: +6
2: +11
3:
3.1:
3.1.1: +6 * (3+2)
3.1.2: +5
3.2: *
3.2.1: +2
3.2.2: *+10
3.2.3: /+5
4:
4.1: +5 * (2 * 6)
4.1.1: +5
4.1.2: * (2 * 6)
4.2: +2
y como siga....
Se entiende lo que quiero hacer??? Ya casi tengo mi expresion regular para detectar ecuaciones ^^, lo que si me va a hacer un poco dificil el tema de la separacion (las vueltas), usare recursividad (no me digan que es mala, eso era en epocas cuando todos tenian 64 mb ram, ahora que todos tienen 512 o mas¿No tienen suficiente memoria para gastarla? :xD)
Raul, en wikipedia también había un ejemplo, no lo quice poner, pero en esa página está toda la info acerca de pilas.
Éxitos con tu trabajo.
:o Lo Logre!!! ;D :P
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 calcu
Como 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 :xD
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 ;D
EDIT: Arreglado el tema de los espacios, y el punto (que es una coma en realidad)
Excelente ;-)
Apenas tenga un tiempito le hecharé un ojo.
Un saludo!