RPN Calculator in Bash
This Bash script implements a Reverse Polish Notation (RPN) calculator. It reads input from standard input, interprets each line as an RPN expression, and evaluates the expressions by performing arithmetic calculations.
Usage
To use the RPN calculator, follow these steps:
- Clone the repository or download the
rpn_calculator.sh
file. - Make the script executable by running the following command:
chmod +x rpn_calculator.sh
- Run the script by executing:
./rpn_calculator.sh
- Enter your RPN expressions, one expression per line.
- Press Enter to evaluate each expression.
- The result or an error message will be displayed for each expression.
Examples
- Addition
$ ./rpn_calculator.sh
5 2 +
7
- Subtraction
$ ./rpn_calculator.sh
8 3 -
5
- Multiplication
$ ./rpn_calculator.sh
4 6 *
24
-
Division
$ ./rpn_calculator.sh 10 2 / 5.00
-
Invalid expression
$ ./rpn_calculator.sh
5 +
error
Implementation Details
- The script uses the
IFS
(Internal Field Separator) variable to define delimiters for splitting strings into words, considering space and tab characters as delimiters by default. - Input is read from standard input using the
read
command, storing each line in theexpression
array. - Empty lines are skipped, and the script moves to the next line.
- Tokens in the
expression
array are processed sequentially: - Numbers are validated using regular expressions, and if valid, are pushed onto the stack.
- Operators (
+
,-
,*
,/
) require sufficient operands. If valid, the calculation is performed and the result is updated in the array. - The script relies on the
bc
command-line utility for performing floating-point arithmetic. - If the final expression array has exactly one element, it is the result. Otherwise, an error message is displayed.
The full reverse notation script
#!/usr/bin/env bash
# - iNFO --------------------------------------
#
# Author: wuseman <wuseman@nr1.nu>
# FileName: dc_like_calc_with_bc.sh
# Created: 2023-06-17 (04:52:25)
# Modified: 2023-06-17 (04:52:28)
# Version: 1.0
# License: MIT
#
# iRC: wuseman (Libera/EFnet/LinkNet)
# GitHub: https://github.com/wuseman/
#
# - Description -------------------------------
#
# This bash script is a calculator that performs calculations using Reverse Polish Notation (RPN). It reads input from standard input,
# interprets each line as an RPN expression, and evaluates the expressions by performing arithmetic calculations.
#
# The script supports the following operators:
# - Addition (+)
# - Subtraction (-)
# - Multiplication (*)
# - Division (/)
#
# It uses the 'bc' command for floating-point arithmetic calculations and allows for decimal places in the results.
#
# The script skips empty lines and outputs the result of each expression on a new line. If an expression is invalid or contains insufficient operands, it outputs 'error'.
#
# - End --------------------------------------
IFS=$' \t' # Set the Internal Field Separator (IFS) to include space and tab characters
while read -r -a expression; do
((n = ${#expression[*]}))
# Skip empty lines
if [ $n -eq 0 ]; then continue; fi
((i = 0))
# Process each element in the expression
while :; do
element=${expression[i]}
# Check if the element is a valid number
if [[ $element =~ ^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)$ ]]; then
((++i)) # Increment the index to move to the next element
elif [[ $element =~ ^[-+*/]$ ]]; then
# Check if there are enough operands to perform the operation
if [ $i -lt 2 ]; then break; fi
# Perform the calculation using the appropriate operator
case $element in
"+") expression[i - 2]=$(echo "${expression[i - 2]} + ${expression[i - 1]}" | bc) ;; # Addition
"-") expression[i - 2]=$(echo "${expression[i - 2]} - ${expression[i - 1]}" | bc) ;; # Subtraction
"*") expression[i - 2]=$(echo "${expression[i - 2]} * ${expression[i - 1]}" | bc) ;; # Multiplication
"/") expression[i - 2]=$(echo "scale=2; ${expression[i - 2]} / ${expression[i - 1]}" | bc) ;; # Division
esac
# Remove the used operands and operator from the array
expression[i]=
((--i)) # Decrement the index to adjust for the removed elements
expression[i]=
((n -= 2)) # Adjust the number of elements in the expression
expression=("${expression[@]}") # Compact the array by removing the empty elements
else
break
fi
# Check if all elements have been processed
if [ $i -eq $n ]; then break; fi
done
# Check if the result is valid and print it, or print an error message
if [ $i -eq $n ] && [ $n -eq 1 ]; then
echo "${expression}" # Output the result
else
echo 'error' # Output error message
fi
done