Foro de elhacker.net

Programación => .NET (C#, VB.NET, ASP) => Mensaje iniciado por: clipto en 30 Julio 2009, 05:41 am



Título: calculadora por jerarquia ()*/+- ...C#...
Publicado por: clipto en 30 Julio 2009, 05:41 am
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
Código:
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


Título: Re: calculadora por jerarquia ()*/+- ...C#...
Publicado por: Meta en 30 Julio 2009, 15:46 pm
Interesante.

¿Sabes ahcerlo en modo Visual?

Saludo.


Título: Re: calculadora por jerarquia ()*/+- ...C#...
Publicado por: raul338 en 30 Julio 2009, 16:44 pm
 :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)


Título: Re: calculadora por jerarquia ()*/+- ...C#...
Publicado por: clipto en 31 Julio 2009, 00:47 am
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
Citar
temp1 = 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
Citar
Console.SetCursorPosition(18,6); Console.WriteLine("Resultado = " + operacion[1]);
            Console.ReadKey();
dises que limpie la caja de texto y que coloque ahi el resultado solamente


Título: Re: calculadora por jerarquia ()*/+- ...C#...
Publicado por: h0oke en 31 Julio 2009, 00:57 am
Para hacerlo en modo visual, no bastaría con leer el contenido en una caja de texto?


Título: Re: calculadora por jerarquia ()*/+- ...C#...
Publicado por: raul338 en 31 Julio 2009, 01:20 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)


Título: Re: calculadora por jerarquia ()*/+- ...C#...
Publicado por: clipto en 31 Julio 2009, 01:26 am
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


Título: Re: calculadora por jerarquia ()*/+- ...C#...
Publicado por: h0oke en 31 Julio 2009, 01:29 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?


Título: Re: calculadora por jerarquia ()*/+- ...C#...
Publicado por: 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.


Título: Re: calculadora por jerarquia ()*/+- ...C#...
Publicado por: raul338 en 31 Julio 2009, 01:43 am
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.

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


Título: Re: calculadora por jerarquia ()*/+- ...C#...
Publicado por: h0oke en 31 Julio 2009, 01:46 am
Citar
Una 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.

Citar
es 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!


Título: Re: calculadora por jerarquia ()*/+- ...C#...
Publicado por: raul338 en 31 Julio 2009, 01:52 am
Citar
Una 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

Citar
es 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


Título: Re: calculadora por jerarquia ()*/+- ...C#...
Publicado por: h0oke en 31 Julio 2009, 01:58 am
Citar
Dividir 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!


Título: Re: calculadora por jerarquia ()*/+- ...C#...
Publicado por: raul338 en 31 Julio 2009, 02:29 am
Citar
Dividir 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  :-\


Título: Re: calculadora por jerarquia ()*/+- ...C#...
Publicado por: h0oke 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.


Título: Re: calculadora por jerarquia ()*/+- ...C#...
Publicado por: raul338 en 31 Julio 2009, 16:52 pm
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


Título: Re: calculadora por jerarquia ()*/+- ...C#...
Publicado por: h0oke en 31 Julio 2009, 16:58 pm
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".


Título: Re: calculadora por jerarquia ()*/+- ...C#...
Publicado por: fuenteRea en 31 Julio 2009, 17:08 pm
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!!º


Título: Re: calculadora por jerarquia ()*/+- ...C#...
Publicado por: h0oke en 31 Julio 2009, 17:13 pm
Cita a wikipedia:

Citar
En 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.

 
Citar
Expresió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  ;)


Título: Re: calculadora por jerarquia ()*/+- ...C#...
Publicado por: raul338 en 31 Julio 2009, 21:10 pm
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


Título: Re: calculadora por jerarquia ()*/+- ...C#...
Publicado por: clipto en 1 Agosto 2009, 01:29 am
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?


Título: Re: calculadora por jerarquia ()*/+- ...C#...
Publicado por: h0oke en 1 Agosto 2009, 03:37 am
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..


Título: Re: calculadora por jerarquia ()*/+- ...C#...
Publicado por: raul338 en 1 Agosto 2009, 16:16 pm
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)

Citar
1: +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

Citar
1: +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:

Citar
1: +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)


Título: Re: calculadora por jerarquia ()*/+- ...C#...
Publicado por: h0oke en 1 Agosto 2009, 17:05 pm
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.


Título: Re: calculadora por jerarquia ()*/+- ...C#...
Publicado por: raul338 en 3 Agosto 2009, 21:00 pm
 :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
Código
  1. Imports System.Text.RegularExpressions
  2.  
  3. Module Module1
  4.  
  5.    Sub Main()
  6.        Dim opcion As String = ""
  7.        Console.WriteLine("Ingrese una operacion combinada o 'end' para salir")
  8.  
  9.        Do
  10.            opcion = Console.ReadLine()
  11.  
  12.            If opcion = "end" Then Exit Do
  13.  
  14.            Try
  15.                Console.WriteLine("Resultado: " & Eval(opcion).ToString("N"))
  16.            Catch ex As Exception
  17.                Console.ForegroundColor = ConsoleColor.White
  18.                Console.WriteLine("Error: " & ex.Message)
  19.                Console.ForegroundColor = ConsoleColor.Gray
  20.            End Try
  21.        Loop
  22.    End Sub
  23.  
  24.    Public Function Eval(ByVal operacion As String) As Double
  25.        Dim resp As Double = 0D
  26.        Dim temp As Double = 0D
  27.  
  28.        operacion = operacion.Replace(" ", "")
  29.        operacion = operacion.Replace(".", ",")
  30.  
  31.        Dim RegexObj As New Regex( _
  32.            "(?<Termino>[+\-]?  (?: \d [\d,*/]* | \( [\d,+\-*/]* \) (?: [*/] \d | [*/] \( [\d,+\-*/]* \) )* ) )", _
  33.            RegexOptions.IgnorePatternWhitespace)
  34.        If RegexObj.IsMatch(operacion) Then
  35.            Dim MatchResults As MatchCollection = RegexObj.Matches(operacion)
  36.            Dim MatchResult As Match = MatchResults(0)
  37.            Dim termino As String
  38.            For i As Int32 = 0 To MatchResults.Count - 1
  39.                termino = MatchResult.Groups("Termino").Value
  40.                If IsNumeric(termino) Then
  41.                    temp = Double.Parse(termino)
  42.                Else
  43.                    ' No podemos pasarle +(5+5)*2 porque lo tomaria como termino y entraria en un bucle infinito
  44.                    ' asi que le extraemos el signo, por defecto le ponemos como positivo y despues le volvemos al
  45.                    ' signo que debe tener
  46.                    Dim signo As Integer = 1
  47.  
  48.                    If termino.Substring(0, 1) = "-" Then
  49.                        signo = -1
  50.                        termino = termino.Substring(1)
  51.                    ElseIf termino.Substring(0, 1) = "+" Then
  52.                        signo = 1
  53.                        termino = termino.Substring(1)
  54.                    End If
  55.                    temp = ResolverTermino(termino)
  56.  
  57.                    temp *= signo ' Multiplicamos por -1 para cambiar el signo, por 1 para mantenerlo igual
  58.                End If
  59.  
  60.                resp += temp
  61.                MatchResult = MatchResult.NextMatch()
  62.            Next
  63.  
  64.            Return resp
  65.        Else
  66.            Throw New Exception("La operacion no pudo ser reconocida")
  67.        End If
  68.    End Function
  69.  
  70.    Function ResolverTermino(ByVal Termino As String) As Double
  71.        Dim resp As Double = 0D
  72.        Dim temp As Double = 0D
  73.  
  74.        Dim RegexObj As New Regex("(?<Termino> [\+\-]?\( .* \) | [\*\/] \d*\,?\d* | [\+\-]? \d*\,?\d* )", RegexOptions.IgnorePatternWhitespace)
  75.  
  76.        If RegexObj.IsMatch(Termino) Then
  77.  
  78.            Dim MatchResults As MatchCollection = RegexObj.Matches(Termino)
  79.            Dim MatchResult As Match = MatchResults(0)
  80.            Dim subTermino As String
  81.            For I As Int32 = 0 To MatchResults.Count - 2
  82.                subTermino = MatchResult.Groups("Termino").Value
  83.                If IsNumeric(subTermino) Then
  84.                    resp = Double.Parse(subTermino)
  85.                Else
  86.                    Select Case subTermino.Substring(0, 1)
  87.                        Case "*"
  88.                            temp = Double.Parse(subTermino.Substring(1))
  89.                            resp *= temp
  90.                        Case "/"
  91.                            temp = Double.Parse(subTermino.Substring(1))
  92.                            resp /= temp
  93.                        Case Else
  94.                            resp = Eval(Regex.Match(subTermino, "\((?<Operacion>.*)\)").Groups("Operacion").Value)
  95.                    End Select
  96.                End If
  97.                MatchResult = MatchResult.NextMatch
  98.            Next
  99.            Return resp
  100.        Else
  101.            Throw New Exception("Parte de la operacion no pudo ser reconocida")
  102.        End If
  103.    End Function
  104. 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)


Título: Re: calculadora por jerarquia ()*/+- ...C#...
Publicado por: h0oke en 4 Agosto 2009, 00:39 am
Excelente  ;-)

Apenas tenga un tiempito le hecharé un ojo.

Un saludo!