Evaluar expresiones matemáticas en C y C++

En este post te mostraré cómo evaluar expresiones matemáticas a partir de una cadena. Es decir, hacer que se evalúe una ecuación, fórmula, etcétera.

De este modo podemos hacer que, por ejemplo, un usuario introduzca una fórmula, introduzca sus valores y se resuelva.

Además de evaluar expresiones aritméticas también podremos proporcionar valores a las variables dentro de la misma.

Vamos a usar tinyexpr, un pequeño analizador para expresiones matemáticas. Si bien el código aquí está destinado a ser usado con C, puede compilar, con ciertos ajustes, para C++.

Descargando librería

Este analizador es muy pequeño (su nombre lo dice) así que basta con incluir al archivo principal y el encabezado; esto es, tinyexpr.h y tinyexpr.c.

Ambos archivos están en el repositorio oficial, pero dejo los enlaces aquí:

  1. https://github.com/codeplea/tinyexpr/blob/master/tinyexpr.h
  2. https://github.com/codeplea/tinyexpr/blob/master/tinyexpr.c

Entramos al enlace y los descargamos, ya sea haciendo click en Raw y luego guardando el archivo, o copiando y pegando.

Incluyendo tinyexpr en proyecto

Ahora al compilar solo debes incluir estos dos archivos; depende de tu compilador (por eso es que recomiendo usar gcc).

Si usas GCC simplemente coloca ambos archivos en el directorio en donde está tu código principal, y en tu código principal usa include:

Luego, compila normalmente con:

gcc main.c

Eso suponiendo que tu archivo se llama main.c. Ahora bien, si usas clang hay que cambiar un poco las cosas.

En tu encabezado solo incluye a tinyexpr.h pero al compilar incluye tinyexpr.c; algo así:

clang main.c tinyexpr.c

Y si estás en Linux con clang usa algo como:

clang-7 -pthread -lm -o main main.c tinyexpr.c

Dicho eso, comencemos con los ejemplos.

Evaluando una simple expresión

Hagamos nuestro “hola mundo” usando esta librería. Vamos a usar la función te_interp que toma dos parámetros: la expresión y un apuntador a una variable en donde colocará el error si es que lo hay.

Vamos a manejar el error en el último ejemplo, por ahora lo vamos a dejar así. Esta función devuelve un double, que es el resultado de la expresión:

Al ejecutar el programa, la salida es:

2^3 * 5 es: 40.000000

Como ves estamos elevando el 2 a la potencia 3 y luego multiplicando por 5, así que es 8 multiplicado por 5 que al final da 40, por lo que estamos evaluando la expresión matemática a partir de la cadena.

Por ahora no estamos enviando ninguna variable; solo estamos evaluando, si lo vemos así, números literales.

Puedes probar el ejemplo en línea.

Variables dentro de la expresión

No siempre vamos a querer resolver una expresión matemática en C usando números literales; habrá ocasiones en las que necesitamos pasarle variables.

Para ello debemos definir las variables, después crear un arreglo de tipo te_variable y finalmente creamos una expresión con te_compile. Aunque suene complejo, no lo es.

Comenzamos definiendo lo necesario:

Vamos a resolver la expresión x * y * z * pow(x, y); si te fijas, se puede usar pow o el operador ^ para elevar un número. Dentro de la expresión se utilizará a x, y y z por eso es que creamos un arreglo y le pasamos el nombre de la variable, y el apuntador a la variable.

Más abajo definimos el número de variables, que son 3 en este caso, pues la función requiere que le digamos cuántas variables son (por ello de los arreglos, apuntadores a arreglos, funciones, etcétera)

Ahora compilamos la expresión:

Eso nos devolverá un apuntador a una variable de tipo te_expr, más tarde debemos liberar la memoria ocupada por la misma usando te_free. Lo importante por el momento es verificar que no se haya regresado un apuntador nulo, lo cual indica que hay un error en la expresión.

Llegados a este punto podemos invocar a te_eval pasándole la expresión, y se resolverá de acuerdo al valor de las variables.

Ya no será necesario compilar la expresión de nuevo, pues como pasamos el apuntador a la variable, siempre que evaluemos la expresión se tomará el valor actual.

En este caso estoy solicitando el valor de las variables por teclado usando scanf; no es estrictamente necesario hacer esto, pues puedes definir las variables como tú quieras.

El código completo es:

Si lo ejecutamos veremos que la expresión se resuelve de manera correcta:

Evaluar expresión matemática en C pasando valor de las variables

Puedes ejecutar el código en línea.

Manejo de errores

Se puede pasar el apuntador a una variable que tendrá el error. Ese error tendrá la posición en la que se encontró al mismo.

Si el error es 0 entonces no hubo error, vamos a probar con una expresión que intencionalmente no está correcta:

Si lo ejecutamos, el programa indica que hay un error en la columna 6; y es porque seguramente esperaba un operando o expresión después del operador, pero no encontró nada.

De este modo manejamos errores y prevenimos comportamientos inesperados. Si quieres puedes ejecutar el código en línea.

Compilar en Visual Studio 2010

Un lector del blog me envió un mensaje indicando cómo compilarlo en Visual Studio 2010. Me envió lo siguiente y me comentó lo siguiente:

El archivo tinyExpr.c no es “C” estándar, no se puede compilar con el VisualStudio. Lo he renombrado por tinyExpr.cpp. Hay declaraciones de variables
en mitad de un bloque de instrucciones. El compilador del VisualStudio no lo permite. Se soluciona renombrando el archivo a .cpp

Nota: yo no lo he probado en Visual Studio 2010 ya que prefiero compilar con GCC actualizado, así que no puedo confirmar si funciona.

Conclusión

Este analizador matemático en C soporta varias cosas. Por ejemplo, soporta la invocación a pow; operaciones comunes y además otras funciones como fac (para el factorial), ncr para el número de combinaciones, entre otros.

También define algunas constantes como Pi o e. Recuerda que puedes darle un vistazo en el repositorio de GitHub.

Encantado de ayudarte


Estoy disponible para trabajar en tu proyecto, modificar el programa del post o realizar tu tarea pendiente, no dudes en ponerte en contacto conmigo.

No te pierdas ninguno de mis posts

Suscríbete a mi canal de Telegram para recibir una notificación cuando escriba un nuevo tutorial de programación.

1 comentario en “Evaluar expresiones matemáticas en C y C++”

Dejar un comentario