The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

RPN - Perl extension for Reverse Polish Math Expression Evaluation

SYNOPSIS

use Math::RPN;
$value=rpn(expr);
@array=rpn(expr);

DESCRIPTION

The rpn function will take a scalar which contains an RPN expression as a set of comma delimited values and operators, and return the result or stack, depending on context. If the function is called in an array context, it will return the entire remaining stack. If it is called in a scalar context, it will return the top item of the stack. In a scalar context, if more than one value remains on the stack, a warning will be sent to STDERR.

In the event of an error, an error message will be sent to STDERR, and rpn will return undef.

The expression can contain any combination of values and operators. Any value which is not an operator is assumed to be a value to be pushed onto the stack.

An explanation of Reverse Polish Notation is beyond the scope of this document, but it I will describe it briefly as a stack-based way of writing mathematical expressions. This has the advantage of eliminating the need for parenthesis and simplifying parsing for computers vs. normal algebraic notation at a slight cost in the ability of humans to easily comprehend the expressions.

OPERATORS

The following operators are supported in the RPN evaluator:

Operator        Operation
+,ADD           [a][b]->[a+b]
-,SUB           [a][b]->[a-b]
*,MUL           [a][b]->[a*b]
/,DIV           [a][b]->[a/b]
%,MOD           [a][b]->[a%b]
POW             [a][b]->[a^b]
SQRT            [a]->[sqrt(a)]
SIN             [a]->[sin(a)]
COS             [a]->[cos(a)]
LOG             [a]->[log(a)]
EXP             [a]->[e^a]
<,LT            [a][b]->(a<b ? [1] : [0])
<=,LE           [a][b]->(a<=b ? [1] : [0])
=,==,EQ         [a][b]->(a==b ? [1] : [0])
>,GT            [a][b]->(a>b ? [1] : [0])
>=,GE           [a][b]->(a>=b ? [1] : [0])
!=,NE           [a][b]=>(a!=b ? [1] : [0])
IF              [a][b][c]-> (a!=0 ? [b] : [c])
DUP             [a]->[a][a]
EXCH            [a][b]->[b][a]
POP             [a][b]->[a]
MIN             [a][b]->([a]<[b] ? [a] : [b])
MAX             [a][b]->([a]>[b] ? [a] : [b])
TIME            Pushes current time (seconds since midnight UTC 1970)

In addition, the IF operator supports special constructs for the "then" and "else" clauses on the stack. The construct allows an RPN expression to be enclosed in curly braces ({expr}), which will cause the entire expression to be pushed on to the stack unevaluated. If this expression is to be pushed onto the stack as a result of an IF, it is evaluated at that time. This allows more flexibility in IF statements and provides some performance benefits because any computations in the unused clause are not performed.

An example would look like so:

1,{,5,3,+,10,*,},{,1,2,3,+,+,},IF

This example would result in the stack containing 80 at the end of the evaluation. First, the IF would be true because 1, so {,5,3,+,10,*,} would be evaluated and the result placed on the stack.

EXAMPLES

The following are a few examples of RPN expressions for common tasks and to help demonstrate the syntax used in the RPN evaluator...

    100,9,*,5,/,32,+	Convert 100 degrees C to 212 degrees F
			(100*9/5+32)

    5,3,LT,100,500,IF	Yields 500
			(5!<3=0,100,500,IF==500, the "else" clause)

AUTHOR

Owen DeLong, owen@delong.com

SEE ALSO

perl(1).