Evaluar Expresiones

Librería (DLL) con funciones para evaluar expresiones aritméticas y funciones predefinidas

elGuille.EvaluarExpresiones es una DLL (ensamblado de .NET 2.0) que contiene dos clases para realizar cálculos a partir de una cadena con las operaciones a realizar.

Las dos clases que contiene son:

  • EvaluarExpresiones
    • Es la clase base y se puede usar para realizar cálculos sobre expresiones aritméticas
    • Los valores numéricos pueden llevar decimales, en ese caso, deben indicarse con el punto.
      Si la configuración regional de Windows usa la coma, el resultado se devolverá con una coma.
      Esto ya no es así…SIEMPRE SE DEVUELVE CON PUNTO PARA LOS DECIMALES.

      Aunque si usas las clases desde el formulario Web, ahí tendrás que poner la coma si el servidor está en España, como es en este caso, al menos para algunas cosas…
    • Las operaciones que se pueden realizar son:
      ^ potencia: 2 ^ 3 = 8
      *, / multiplicación y división. También se puede usar la x.
      \ división entera (se convierten a Long (Int64) y se devuelve un Long.
      +, – suma y resta
      % cálculo de porcentaje, 100 % 5 = 5% de 100 = 5
      (Ɯ o ɯ) (código 412, la m invertida) también la m, para calcular el residuo de una división (mod)
    • Las expresiones se pueden encerrar entre paréntesis para cambiar el orden de evaluación.
  • EvaluarFunciones
    • Esta clase se deriva de EvaluarExpresiones, y además de realizar los mismos cálculos que la clase base, permite usar funciones predefinidas, por ejemplo Rnd, Pi, Round, etc.
    • Esas funciones (salvo Pi, E y una de las versiones de Rnd) reciben valores como argumento, esos valores serán los que la función use para realizar el cálculo.
    • Siempre hay que usar los paréntesis en las funciones, incluso si no se indican argumentos.
      Esto tampoco es del todo cierto, ya que las funciones que no reciben parámetros se pueden usar sin los paréntesis, pero lo mejor es usarlos siempre.
    • Unas funciones usan 1 argumento, otras (la mayoría) usan dos y otras permiten usar un número indeterminado de argumentos, por ejemplo, Max, Min, Sum, etc.
    • Esos argumentos también pueden ser expresiones a calcular, por ejemplo:
      Sum(10 * 25, 12 ^ 4)
    • Las funciones se pueden usar en una expresión, por ejemplo:
      Max(1, 2, 23, 5) * 2
      En este caso, se usará el valor devuelto (23) y se multiplicará por dos.
    • Los distintos parámetros habrá que indicarlos separados por comas.
    • Por ahora, las funciones no deben usar otras funciones como argumentos, salvo si la función no recibe parámetros, (por ejemplo Pi()) o solo recibe un parámetro.
      Ejemplo: Min(100, 22, 23, 555, Pi(), Rnd(6))

      Esto tampoco es cierto (es que lo escribí ayer y he hecho un montón de cambios), ahora se pueden anidar funciones dentro de otras funciones, por ejemplo:
      Max(100, 22, 23, 555, Pi() * 100 * E(), Fact(Min(10, 20, 2.99)))
    • Tampoco se pueden usar valores decimales (ni aunque se use el punto), si esos valores son por el resultado de un cálculo, no hay problemas.
      Esto tampoco es cierto… je, je ¡que mentiroso me he vuelto de un día para otro!
      Se pueden usar decimales, lo que ahora mismo no hace bien (versión 1.0.0.38), es evaluar correctamente los valores indicados, al menos en el sentido de que no hace comprobación de prioridad de operadores y no se lleva muy bien con las cosas encerradas entre paréntesis, salvo que sean otras funciones.
    • Las funciones soportadas son (por orden alfabético):
      <%= EvaluarFunciones.FuncionesSoportadas().Replace(vbCrLf, «
      «) %>

      En cualquier momento puedes ver cuales son usando el método compartido FuncionesSoportadas.

Esas clases se pueden usar creando una instancia y usando el método Evalua o bien se puede usar el método compartido Evaluar, con lo que no será necesario crear un objeto en la memoria.

En el caso de Factorial, el valor máximo soportado es 170!, cualquier valor mayor de 170 produce Infinito.
No es problema de la DLL, sino que .NET no soporta valores mayores de 1,79769313486232E+308
y el factorial de 170 es 7,25741561530799E+306, así que…

Si te interesa, el factorial de 171 es:
12410180702176678234248405241031039926166055775016931853889518036119960752216917 52992751978120487585576464959501670387052809889858690710767331242032218484364310 47357788996854827829075454156196485215346831804429323959817369689965723590394761 6152278558180061176365108428800000000000000000000000000000000000000000
Y si no me crees… ¡haz el cálculo! ;-)))

Como te imaginarás, existen relaciones entre los operadores y algunas funciones, por ejemplo:
10 m 3  es lo mismo que Mod(10, 3)
10 * 2 es lo mismo que Mult(10, 2)
10 / 2 es lo mismo que Div(10, 2)
10 \ 2 es lo mismo que DivInt(10, 2)
10 ^ 2 es lo mismo que Pow(10, 2)
10 + 2 es lo mismo que Sum(10, 2)
10 – 2 es lo mismo que Subst(10, 2)
10 % 2 es lo mismo que Percent(10, 2)

También existen funciones que están es castellano, por ejemplo:
Suma, Resta, Divide, Multiplica, Porcentaje y Factorial.

Igualmente, hay funciones que hacen lo mismo, pero que usan dos nombres (independiente de que estén en inglés):
Sqr y Sqrt. Esto es porque en VB6 se usa Sqr y en la clase Math, se usa Sqrt (nostálgico que es uno).
Sgn y Sign, mismo motivo que la anterior, Sgn es la compatible con VB6 y Sign es la de la clase Marh.

Además de los cálculos, también existen 5 métodos que se pueden usar para convertir entre tipos numéricos:

  • DecToBin, convierte de decimal a binario (en base 2), se puede indicar el número de dígitos a usar, (default: 32).
    • El resultado se agrupa de 4 en 4 dígitos y se eliminan los ceros que haya al principio, por tanto, si conviertes el número 25 a binario, te dará: 1 1001 independientemente del número de cifras que le indiques. Es decir, el número de cifras es el máximo que devolverá.
  • DecToOct, convierte de decimal a octal (en base 8).
  • DecToHex, convierte de decimal a hexadecimal (base 16), se puede indicar el número de dígitos (default 16).
    • Mismo comentario que para DecToBin.
  • OctToDec, convierte de octal a decimal.
  • BinToDec, convierte de binario a decimal (base 10).

En los cuatro primeros casos, el parámetro que recibe es de tipo Object, que se convierte a Long (Int64) y devuelve una cadena (String).
BinToDec, recibe una cadena y devuelve un Long (Int64). Se ignorará cualquier cosa que no sea un 0 o un 1.

Nota del 17/Oct/07:
Las actualizaciones a esta librería las iré publicando en la página de Actualizaciones de EvaluarExpresiones.