Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/grinnz/math-calc-parser
Math::Calc::Parser - Parse and evaluate mathematical expressions
https://github.com/grinnz/math-calc-parser
Last synced: 5 days ago
JSON representation
Math::Calc::Parser - Parse and evaluate mathematical expressions
- Host: GitHub
- URL: https://github.com/grinnz/math-calc-parser
- Owner: Grinnz
- License: other
- Created: 2015-03-03T00:48:48.000Z (almost 10 years ago)
- Default Branch: master
- Last Pushed: 2019-10-08T21:39:35.000Z (about 5 years ago)
- Last Synced: 2024-11-13T05:43:07.899Z (about 2 months ago)
- Language: Perl
- Homepage: https://metacpan.org/pod/Math::Calc::Parser
- Size: 98.6 KB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 3
-
Metadata Files:
- Readme: README.pod
- Changelog: Changes
- Contributing: CONTRIBUTING.md
- License: LICENSE
Awesome Lists containing this project
README
=pod
=encoding utf8
=head1 NAME
Math::Calc::Parser - Parse and evaluate mathematical expressions
=head1 SYNOPSIS
use Math::Calc::Parser 'calc';
use utf8; # for π in source code
my $result = calc '2 + 2'; # 4
my $result = calc 'int rand 5'; # Random integer between 0 and 4
my $result = calc 'sqrt -1'; # i
my $result = calc '0xff << 2'; # 1020
my $result = calc '1/0'; # Division by 0 exception
# Class methods
my $result = Math::Calc::Parser->evaluate('2 + 2'); # 4
my $result = Math::Calc::Parser->evaluate('3π^2'); # 29.608813203268
my $result = Math::Calc::Parser->evaluate('0.7(ln 4)'); # 0.970406052783923
# With more advanced error handling
my $result = Math::Calc::Parser->try_evaluate('rand(abs'); # undef (Mismatched parentheses)
if (defined $result) {
print "Result: $result\n";
} else {
print "Error: ".Math::Calc::Parser->error."\n";
}
# Or as an object for more control
my $parser = Math::Calc::Parser->new;
$parser->add_functions(triple => { args => 1, code => sub { $_[0]*3 } });
$parser->add_functions(pow => { args => 2, code => sub { $_[0] ** $_[1] });
$parser->add_functions(one => sub { 1 }, two => sub { 2 }, three => sub { 3 });
my $result = $parser->evaluate('2(triple one)'); # 2*(1*3) = 6
my $result = $parser->evaluate('pow(triple two, three)'); # (2*3)^3 = 216
my $result = $parser->try_evaluate('triple triple'); # undef (Malformed expression)
die $parser->error unless defined $result;
$parser->remove_functions('π', 'e');
$parser->evaluate('3π'); # Invalid function exception
# Arbitrary precision calculations - use only in a controlled environment
$parser->bignum(1);
my $result = $parser->evaluate('30!'); # 265252859812191058636308480000000
my $result = $parser->evaluate('atan pi'); # 1.262627255678911683444322083605698343509
# Rational number calculations - use only in a controlled environment
$parser->bigrat(1);
my $result = $parser->evaluate('3 / 9'); # 1/3
my $result = $parser->evaluate('3 >> 2'); # 3/4=head1 DESCRIPTION
L is a simplified mathematical expression evaluator with
support for complex and trigonometric operations, implicit multiplication, and
perlish "parentheses optional" functions, while being safe for arbitrary user
input. It parses input strings into a structure based on
L
(RPN), and then evaluates the result. The list of recognized functions may be
customized using L"add_functions"> and L"remove_functions">.=head1 FUNCTIONS
=head2 calc
use Math::Calc::Parser 'calc';
my $result = calc '2+2';
$ perl -MMath::Calc::Parser=calc -E 'say calc "2+2"'
$ perl -Math -e '2+2'Compact exportable function wrapping L"evaluate"> for string expressions.
Throws an exception on error. See L for easy compact one-liners.=head1 ATTRIBUTES
These attributes can only be set on instantiated objects.
=head2 bignum
my $bool = $parser->bignum;
$parser = $parser->bignum($bool);Enable support for arbitrary precision numbers using L and
L. This will avoid losing precision when working with floats or
large integers, but see L"BIGNUM CAVEATS">.=head2 bigrat
my $bool = $parser->bigrat;
$parser = $parser->bigrat($bool);Enable support for precise rational numbers using L. This will
avoid losing precision when working with integer divison and similar
operations, and will result in output like C<3/7> where possible, but see
L"BIGNUM CAVEATS">.=head1 METHODS
Aside from C and C, all methods can be called
as class methods, and will act on a singleton object with the default functions
available.=head2 new
my $parser = Math::Calc::Parser->new;
my $parser = Math::Calc::Parser->new(bignum => 1);Creates a new L object.
=head2 parse
my $parsed = Math::Calc::Parser->parse('5 / e^(i*pi)');
my $parsed = $parser->parse('3pi');Parses a mathematical expression. On success, returns an array reference
representation of the expression in RPN notation which can be passed to
L"evaluate">. Throws an exception on failure.=head2 evaluate
my $result = Math::Calc::Parser->evaluate($parsed);
my $result = Math::Calc::Parser->evaluate('log rand 7');
my $result = $parser->evaluate('round 13/3');Evaluates a mathematical expression. The argument can be either an arrayref
from L"parse"> or a string expression which will be passed to L"parse">.
Returns the result of the expression on success or throws an exception on
failure.=head2 try_evaluate
if (defined (my $result = Math::Calc::Parser->try_evaluate('floor 2.5'))) {
print "Result: $result\n";
} else {
print "Error: ".Math::Calc::Parser->error."\n";
}
if (defined (my $result = $parser->try_evaluate('log(5'))) {
print "Result: $result\n";
} else {
print "Error: ".$parser->error."\n";
}Same as L"evaluate"> but instead of throwing an exception on failure, returns
undef. The L"error"> method can then be used to retrieve the error message.
The error message for the most recent L"try_evaluate"> call can also be
retrieved from the package variable C<$Math::Calc::Parser::ERROR>.=head2 error
my $result = Math::Calc::Parser->try_evaluate('(i');
die Math::Calc::Parser->error unless defined $result;
my $result = $parser->try_evaluate('2//');
die $parser->error unless defined $result;Returns the error message after a failed L"try_evaluate">.
=head2 add_functions
$parser->add_functions(
my_function => { args => 5, code => sub { return grep { $_ > 0 } @_; } },
other_function => sub { 20 },
bignum_function => { args => 1, code => sub { 2 ** $_[0] }, bignum_code => sub { Math::BigInt->new(2)->bpow($_[0]) } },
);Adds functions to be recognized by the parser object. Keys are function names
which must start with an alphabetic character and consist only of
L.
Values are either a hashref containing C and Ckeys, or a coderef
that is assumed to be a 0-argument function. C must be an integer greater
than or equal to C<0>. Cor the passed coderef will be called with the
numeric operands passed as parameters, and must either return a numeric result
or throw an exception. Non-numeric results will be cast to numbers in the usual
perl fashion, and undefined results will throw an evaluation error.Alternate implementations to be used when L"bignum"> or L"bigrat"> is
enabled can be passed as C and C respectively.
C will also be used for L"bigrat"> calculations if
C is not separately defined; it is not common that these will need
separate implementations.=head2 remove_functions
$parser->remove_functions('rand','nonexistent');
Removes functions from the parser object if they exist. Can be used to remove
default functions as well as functions previously added with
L"add_functions">.=head1 OPERATORS
L recognizes the following operators with their usual
mathematical definitions.+, -, *, /, %, ^, !, <<, >>
Note: C<+> and C<-> can represent both binary addition/subtraction and unary
negation.=head1 DEFAULT FUNCTIONS
L parses several functions by default, which can be
customized using L"add_functions"> or L"remove_functions"> on an object
instance.=over
=item abs
Absolute value.
=item acos
=item asin
=item atan
Inverse sine, cosine, and tangent.
=item atan2
Two-argument inverse tangent of first argument divided by second argument.
=item ceil
Round up to nearest integer.
=item cos
Cosine.
=item e
Euler's number.
=item floor
Round down to nearest integer.
=item i
Imaginary unit.
=item int
Cast (truncate) to integer.
=item ln
Natural log.
=item log
Log base 10.
=item logn
Log with arbitrary base given as second argument.
=item pi
π
=item π
π (this must be the decoded Unicode character)
=item rand
Random value between 0 and 1 (exclusive of 1). Uses L if
installed.=item round
Round to nearest integer, with halfway cases rounded away from zero. Due to
bugs in L, precision may be lost with L"bigrat"> enabled.=item sin
Sine.
=item sqrt
Square root.
=item tan
Tangent.
=back
=head1 CAVEATS
While parentheses are optional for functions with 0 or 1 argument, they are
required when a comma is used to separate multiple arguments.Due to the nature of handling complex numbers, the evaluated result may be a
L object. These objects can be directly printed or used in
numeric operations but may be more difficult to use in comparisons.Operators that are not defined to operate on complex numbers will return the
result of the operation on the real components of their operands. This includes
the operators CE>, CE>, C<%>, and C.=head1 BIGNUM CAVEATS
The L, L, and L packages are useful
for working with numbers without losing precision, and can be used by this
module by setting the L"bignum"> or L"bigrat"> attributes, but care should
be taken. They will perform significantly slower than native Perl numbers, and
can result in an operation that does not terminate or one that uses up all your
memory.Additionally, similar to when using the L or L pragmas, the
auto-upgrading and downgrading behavior of these modules can only be set
globally, so enabling these options will affect all other uses of these modules
in your program. For the same reason, it is not recommended to enable both
L"bignum"> and L"bigrat"> in the same program.The evaluated result may be a L, L,
L, or other similar type of object. These objects can be printed
and behave normally as numbers.L defaults to rounding values at 40 digits in division. This
can be controlled by setting the global L,
but may have a large impact on performance and memory usage.Complex math is incompatible with L"bignum"> and L"bigrat"> and will likely
result in NaN.=head1 BUGS
Report any issues on the public bugtracker.
=head1 AUTHOR
Dan Book, C
=head1 COPYRIGHT AND LICENSE
Copyright 2015, Dan Book.
This library is free software; you may redistribute it and/or modify it under
the terms of the Artistic License version 2.0.=head1 SEE ALSO
L
=cut