Colabora
 

cFormulas portado a CSharp

Analizador de Expresiones Numéricas en C#.Net

Fecha: 17/Feb/2008 (12-02-08)
Autor: Gino Llerena T. - gino.llerena@gmail.com
Nick: GALleTa

 


Introducción

Teniendo en cuenta que el analizar expresiones numéricas nos resulta importante en la elaboración de aplicaciones que dentro de su procesamiento requieren algún tipo de almacenamiento de variables que serán procesadas por formulas definidas por el usuario y al no haber encontrado una aplicación de éste tipo en la plataforma .Net  y conociendo de la destacada utilidad de cFormulas desarrollado en VB 6.0 es que decido portar ésta aplicación al lenguaje CSharp eliminando toda dependencia a cualquier librería de VB.

Contenido

Para elaborar ésta aplicación se ha hecho uso extensivo de strings y sus funciones relacionadas, también se han utilizado generics para facilitar el manejo de las colecciones, tanto de las funciones definidas como las variables ingresadas; así también se ha intentado agrupar bajo cierta funcionalidad las operaciones relacionadas con el objeto de mejorar el mantenimiento de la aplicación.

Nota:
Cabe notar que algunas características de la aplicación original han sido dejadas de lado pues al momento de portar ésta aplicación no me fueron de utilidad sin embargo es totalmente factible su inclusión.

El código:

Con el objetivo de portar la aplicación cFormulas a CSharp se procedió a redefinir todas las rutinas de manejo de cadenas de caracteres teniendo en consideración la funcionalidad que provee la plataforma .Net. Además como ya se ha mencionado se procedió a identificar las operaciones que compartían una determinada funcionalidad con el objeto de agruparlos en Clases y así poder tener un código mas modular y ágil en su mantenimiento.

  • Relación de Clases e Interfaces:
    • Function Clase que referencia una función pre-definida.
    • Functions Clase que hereda de una lista genérica de Function.
    • Variable Clase que registra una variable ingresada.
    • Variables Clase que hereda de una lista genérica de Variable.
    • IFunctionProcessor Interfaz que define las funcionalidad del Procesador de Funciones
    • FunctionProcessor Clase que implementa el Procesamiento de Funciones
    • IOperatorProcessor Interfaz que define las funcionalidad del Procesador de Operadores
    • OperatorProcessor Clase que implementa el Procesamiento de Operadores
    • BaseEval Clase abstracta que define la funcionalidad del evaluador de expresiones numéricas
    • MathProcessor Clase que implementa la funcionalidad del evaluador de expresiones

Diagrama de Clases.

GALleTa_cFormulasCSharp.jpg

Código principal de OperatorProcessor:

private double  CalculateByOperator(double n1, double n2, string op) 
{ 

            double n3=0;  
 
            switch (op)  
            { 
                case "+": n3 = n1 + n2; breakcase "-": n3 = n1 - n2; breakcase "*": n3 = n1 * n2; breakcase "/": if (n2 != 0) n3 = n1 / n2; 
                          else n3 = 0; 
                          breakcase "^": n3 = Math.Pow(n1, n2); break; 
 
                case "%": n3 = n1 % n2; break; 
 
                default: 
                    { 
                        n3 = n1 + n2; 
                        break; 
                    } 
            } 
 
            return n3;  

} 

Código principal de FunctionProcessor :

public string   Process(string sNameFun, string[] parameters) 
 
{ 
    string sReturn = ""; 
 
    switch (sNameFun) 
    { 
        case "Int": sReturn = "(" + Math.Floor(decimal.Parse(parameters[0])).ToString() + ")"; breakcase "Fix": sReturn = "(" +  
         (Math.Sign(double.Parse(parameters[0]))*Math.Floor(Math.Abs(decimal.Parse(parameters[0])))).ToString()
         + ")"; breakcase "Abs": sReturn = "(" + Math.Abs(double.Parse(parameters[0])).ToString() + ")"; breakcase "Sgn": sReturn = "(" + Math.Sign(double.Parse(parameters[0])).ToString() + ")"; breakcase "Sqr": sReturn = "(" + Math.Sqrt(double.Parse(parameters[0])).ToString() + ")"; breakcase "Cos": sReturn = "(" + Math.Cos(double.Parse(parameters[0])).ToString() + ")"; breakcase "Sin": sReturn = "(" + Math.Sin(double.Parse(parameters[0])).ToString() + ")"; breakcase "Tan": sReturn = "(" + Math.Tan(double.Parse(parameters[0])).ToString() + ")"; breakcase "Atn": sReturn = "(" + Math.Atan(double.Parse(parameters[0])).ToString() + ")"; breakcase "Exp": sReturn = "(" + Math.Exp(double.Parse(parameters[0])).ToString() + ")"; breakcase "Log": sReturn = "(" + Math.Log(double.Parse(parameters[0])).ToString() + ")"; breakcase "Max": 
            sReturn = (double.Parse(parameters[0]) > double.Parse(parameters[1])) 
                                                                    ? parameters[0] : parameters[1]; breakcase "Min": 
            sReturn = (double.Parse(parameters[0]) < double.Parse(parameters[1])) 
                                                                    ? parameters[0] : parameters[1]; breakcase "EQ": 
            sReturn = (double.Parse(parameters[0]) == double.Parse(parameters[1])) 
                                                                    ? parameters[2] : parameters[3]; breakcase "NEQ": 
            sReturn = (double.Parse(parameters[0]) != double.Parse(parameters[1])) 
                                                                    ? parameters[2] : parameters[3]; breakcase "LT": 
            sReturn = (double.Parse(parameters[0]) < double.Parse(parameters[1])) 
                                                                    ? parameters[2] : parameters[3]; breakcase "LET": 
            sReturn = (double.Parse(parameters[0]) <= double.Parse(parameters[1])) 
                                                                    ? parameters[2] : parameters[3]; breakcase "GT": 
            sReturn = (double.Parse(parameters[0]) > double.Parse(parameters[1])) 
                                                                    ? parameters[2] : parameters[3]; breakcase "GET": 
            sReturn = (double.Parse(parameters[0]) >= double.Parse(parameters[1])) 
                                                                    ? parameters[2] : parameters[3]; break; 
        } 
         
    return sReturn; 
  
} 

Nota:
Para poder definir más funciones es necesario registrar en el constructor de la Clase FunctionProcessor el nombre de la función, la formula y los parámetros a utilizar:
.
aFunction.AddIfNotExist("Sum", "Num1,Num2,...", "Num1+Num2+...");
.

Finalmente cabe indicar que las clases e interfaces mencionadas han sido agrupadas dentro de una librería cuyo espacio de nombres es Library. Espero que éste articulo y básicamente el código fuente incorporado sirva de utilidad tal y como la versión original lo ha sido para muchos. Saludos


Espacios de nombres usados en el código de este artículo:

System.Windows.Forms
System.Collections.Generic
System.Collections.Specialized

 



Compromiso del autor del artículo con el sitio del Guille:

Lo comentado en este artículo está probado (y funciona) con la siguiente configuración:

El autor se compromete personalmente de que lo expuesto en este artículo es cierto y lo ha comprobado usando la configuración indicada anteriormente.

En cualquier caso, el Guille no se responsabiliza del contenido de este artículo.

Si encuentras alguna errata o fallo en algún link (enlace), por favor comunícalo usando este link:

Gracias.


Código de ejemplo (comprimido):

 

Fichero con el código de ejemplo: GALleTa_cFormulasCSharp.rar - 26.1 KB

Comprobación MD5 de este zip: 7C5BA702A4491DE398EBADC11C6F6676


Ir al índice principal de el Guille