NAME
Math::Expression::Evaluator - parses, compiles and evaluates mathematic
expressions
SYNOPSIS
use Math::Expression::Evaluator;
my $m = new Math::Expression::Evaluator;
print $m->parse("a = 12; a*3")->val(), "\n";
# prints 36
print $m->parse("2^(a/3)")->val(), "\n";
# prints 8 (ie 2**3)
print $m->parse("a / b")->val({ b => 6 }), "\n";
# prints 36
print $m->parse("log2(16)")->val(), "\n";
# prints 4
# if you care about speed
my $func = $m->parse('2 + (4 * b)')->compiled;
for (0 .. 100){
print $func->({b => $_}), "\n";
}
DESCRIPTION
Math::Expression::Evaluator is a parser, compiler and interpreter for
mathematical expressions. It can handle normal arithmetics (includings
powers ^), builtin functions like sin() and variables.
Multiplication "*", division "/" and modulo "%" have the same
precedence, and are evaluated left to right. The modulo operation
follows the standard perl semantics, that is is the arguments are castet
to integer before preforming the modulo operation.
Multiple exressions can be seperated by whitespaces or by semicolons
';'. In case of multiple expressions the value of the last expression is
returned.
Variables can be assigned with a single '=' sign, their name has to
start with a alphabetic character or underscore "[a-zA-Z_]", and may
contain alphabetic characters, digits and underscores.
Values for variables can also be provided as a hash ref as a parameter
to val(). In case of collision the explicitly provided value is used:
$m->parse("a = 2; a")->val({a => 1});
will return 1, not 2.
The following builtin functions are supported atm:
* trignometric functions: sin, cos, tan
* inverse trigonomic functions: asin, acos, atan
* Square root: sqrt
* exponentials: exp, sinh, cosh
* logarithms: log, log2, log10
* constants: pi() (you need the parenthesis to distinguish it from the
variable pi)
* rounding: ceil(), floor()
* other: theta (theta(x) = 1 for x > 0, theta(x) = 0 for x < 0)
METHODS
new
generates a new MathExpr object. accepts an optional argument, a hash
ref that contains configurations. If this hash sets force_semicolon to
true, expressions have to be separated by a semicolon ';'.
parse
Takes a string as argument, and generates an Abstract Syntax Tree(AST)
that is stored internally.
Returns a reference to the object, so that method calls can be
chained:
print MathExpr->new->parse("1+2")->val;
Parse failures cause this method to die with a stack trace.
compiled
Returns an anonymous function that is a compiled version of the
current expression. It is much faster to execute than the other
methods, but its error messages aren't as informative (instead of
complaining about a non-existing variable it dies with "Use of
uninitialized value in...").
Note that variables are not persistent between calls to compiled
functions (and it wouldn't make sense anyway, because such a function
corresponds always to exactly one expression, not many as a MEE
object).
Variables that were stored at the time when "compiled()" is called are
availble in the compiled function, though.
val
Executes the AST generated by parse(), and returns the number that the
expression is evaluated to. It accepts an optional hash reference that
contain values for variables:
my $m = new MathExpr;
$m->parse("(x - 1) / (x + 1)");
foreach (0 .. 10) {
print $_, "\t", $m->val({x => $_}), "\n";
}
optimize
Optimizes the internal AST, so that subsequent calls to "val()" will
be a bit faster. See "Math::Expression::Evaluator::Optimizer" for
performance considerations and informations on the implemented
optimizations.
But note that a call to "optimize()" only pays off if you call "val()"
multiple times.
variables
"variables()" returns a list of variables that are used in the
expression.
ast_size
"ast_size" returns an integer which gives a crude measure of the
logical size of the expression. Note that this value isn't guarantueed
to be stable across multiple versions of this module. It is mainly
intended for testing.
SPEED
MEE isn't as fast as perl, because it is built on top of perl.
If you execute an expression multiple times, it pays off to either
optimize it first, or (even better) compile it to a pure perl function.
Rate no_optimize optimize opt_compiled compiled
no_optimize 83.9/s -- -44% -82% -83%
optimize 150/s 78% -- -68% -69%
opt_compiled 472/s 463% 215% -- -4%
compiled 490/s 485% 227% 4% --
This shows the time for 200 evaluations of "2+a+5+(3+4)" (with MEE
0.0.5). As you can see, the non-optimized version is painfully slow,
optimization nearly doubles the execution speed. The compiled and the
optimized-and-then-compiled versions are both much faster.
With this example expression the optimization prior to compilation pays
off if you evaluate it more than 1000 times. But even if you call it
"10**5" times the optimized and compiled version is only 3% faster than
the directly compiled one (mostly due to perl's overhead for method
calls).
So to summarize you should compile your expresions, and if you have
really many iterations it might pay off to optimize it first (or to
write your program in C instead ;-).
BUGS AND LIMITATIONS
* Modulo operator produces an unnecessary big AST, making it
relatively slow
INTERNALS
The AST can be accessed as "$obj-"{ast}>. Its structure is described in
Math::Expression::Evaluator::Parser (or you can use Data::Dumper to
figure it out for yourself).
SEE ALSO
Math::Expression also evaluates mathematical expressions, but also
handles string operations.
If you want to do symbolic (aka algebraic) transformations,
Math::Symbolic will fit your needs.
LICENSE
This module is free software. You may use, redistribute and modify it
under the same terms as perl itself.
AUTHOR
Moritz Lenz, , moritz@faui2k3.org
DEVELOPMENT
You can obtain the latest development version via subversion:
svn co https://faui2k3.org/svn/moritz/cpan/Math-Expression-Evaluator/