rpn-cli

Crates.iorpn-cli
lib.rsrpn-cli
version1.6.0
created_at2024-03-06 20:42:05.944243+00
updated_at2025-08-02 21:10:54.494372+00
descriptionCommand line reverse Polish notation calculator.
homepage
repository
max_upload_size
id1165197
size630,973
Huw Walters (hdwalters)

documentation

README

Reverse Polish Notation Calculator

Versions

Version Released Change
1.0.0 06-Mar-2024 Initial version.
1.1.0 20-May-2024 Import values and operations from file with import directive or --import option.
Export results to file with export directive.
Define custom functions with define directive.
Sum values in batch mode with --sum option.
Correct floating point errors by rounding to nearest repeating decimal.
1.2.0 05-Jun-2024 Parse and format hexadecimal as 0x89ab.
Export hexadecimal in batch mode with --hex option.
Export no separators in batch mode or with export directive.
1.3.0 15-Mar-2025 Format and parse time (already in UTC) with "Z".
Format hexadecimal with comma not underscore separators.
Export separators in batch mode with --sep option.
Export precision in batch mode with --dp option.
1.4.0 25-May-2025 Set named variable to most recent entry with set directive, for later use.
Remove defined functions with define directive, and keyword but no body.
Show defined functions with define directive, and no keyword or body.
Show defined functions with derived parameter hints.
Improve inline help and stack history output.
1.5.0 12-Jun-2025 Group values on the stack for sequence operations.
Create and modify sequences with seq, step, sort, rev and flat operations.
Apply unary operation to all values with apply directive.
Copy and duplicate values without variable name.
Undo import file in a single step after import directive or --import option.
Undo cast after plain, delta and time operations.
Show entire stack with show command, or 10 most recent values after an operation.
Show defined variables with set directive and no variable name.
1.6.0 - Apply measurement units to values, with context specific scaling.
Apply formatting to interactive session, with --hex, --sep and --dp options.
Prevent number formatting infinite loops.
Show detailed unit and apply errors.

Contents

Introduction

RPN is a command line reverse Polish notation calculator. As such, it pushes integer and fractional numbers onto a stack, and pops them off for operations, running in interactive mode:

$ rpn
rpn> 6 7
rpn> show
  6
  7
rpn> mul
  42

It accepts input from files supplied on the command line, running in batch mode:

$ cat input.txt
6 7
mul
$ rpn input.txt
42

It accepts input from a POSIX shell command pipeline, running in batch mode:

$ seq 1 5 | rpn --sum
15

It writes output to a POSIX shell command pipeline, running in batch mode:

$ rpn >output.txt
6 7
mul
$ cat output.txt
42

Feature requests are welcome, but it's a hobby project in a language I don't get to use in my day job, so I prefer to do all the development myself.

Program Options

The -c or --command option accepts input directly from the command line:

$ rpn --command 6 7 mul
42

The --import option imports values and operations from a text file. This can be used for commonly used custom functions:

$ cat defines.txt
define cube 3 pow
define percent 100 div
$ rpn --import defines.txt
rpn> 2 cube
  8

The --sum option causes all results to be summed, if running in batch mode:

$ cat numbers.txt
1 2 3 4 5
$ rpn --sum numbers.txt
15
$ rpn --sum --command 1 2 3 4 5
15
$ seq 1 5 | rpn --sum
15

The --hex option causes results to be printed in hexadecimal, if running in batch mode:

$ rpn --hex --command 10 10 mul
0x00000064

The --sep option causes results to be printed with separators, if running in batch mode:

$ rpn --sep --command 10 10 pow
10,000,000,000

Program Features

Some operations are binary like add and mul, some are unary like neg and inv, some are nullary like now, while others operate on the entire stack like sum and prod. Inline help provides hints on expected inputs and outputs:

rpn> help
  Arithmetic operations:
    N N  add,+   N    Add two values
    N N  sub,-   N    Subtract two values
    N N  mul,*   N    Multiply two values
    N N  div,/   N    Divide two values
    N N  mod,%   N    Modulo two values
      N  neg     N    Find the negative
      N  inv     N    Find the inverse
    N N  pow     N    Raise to the power
      N  sqrt    N    Find the square root
      *  sum     N    Sum all values
      *  prod    N    Multiply all values
  Sequence operations:
    N N  seq     *    Generate integer sequence (start to stop)
      3  step    *    Generate integer sequence (start with step to stop)
      *  sort    *    Sort stack or sequence
      *  rev     *    Reverse stack or sequence
      *  flat    *    Flatten entire stack
  Bitwise operations:
    N N  and     N    Bitwise AND two values
    N N  or      N    Bitwise OR two values
    N N  xor     N    Bitwise XOR two values
    N N  shl     N    Shift left (multiply by power of 2)
    N N  shr     N    Shift right (divide by power of 2)
  Time operations:
         now     N    Get the current time (in UTC)
      N  plain   N    Format as a plain value
      N  delta   N    Format as a delta value (duration)
      N  time    N    Format as a time value (in UTC)
  Formatting commands:
         dec          Format as decimal values
         hex          Format as hexadecimal values
         sep          Include comma separators
         nosep        Include no separators
      N  dp           Use fixed decimal places
         nodp         Use free decimal places
  Stack commands:
         show         Show all values on the stack
      *  clear        Remove all values from the stack
      N  pop          Remove a value from the stack
      N  dup     N N  Duplicate a value on the stack
    N N  swap    N N  Swap two values on the stack
      N  cut          Cut a value to the internal clipboard
      N  copy    N    Copy a value to the internal clipboard
         paste   N    Paste a value from the internal clipboard
  History commands:
         u(ndo)       Undo the last operation
         r(edo)       Redo the next operation
         hist         Show all undo/redo history
  General directives:
         import...    Import file e.g. "import file.txt"
         export...    Export file e.g. "export file.txt"
         set,=...     Set variable, e.g. "set x"
         define...    Define function e.g. "define cube 3 pow"
         apply...     Apply to stack or sequence, e.g. "apply 3 pow"
  General commands:
         units        Show unit names and symbols
         help         Show this help text

Arithmetic Operations

The add operation adds two values:

rpn> 5.5 2.5 show
  5.5
  2.5
rpn> add
  8

The sub operation subtracts two values:

rpn> 5.5 2.5 show
  5.5
  2.5
rpn> sub
  3

The mul operation multiplies two values:

rpn> 5.5 2.5 show
  5.5
  2.5
rpn> mul
  13.75

The div operation divides two values:

rpn> 5.5 2.5 show
  5.5
  2.5
rpn> div
  2.2

The mod operation divides two values and finds the remainder:

rpn> 5.5 2.5 show
  5.5
  2.5
rpn> mod
  0.5

The neg operation finds the negative:

rpn> 8 show
  8
rpn> neg
  -8

The inv operation finds the inverse:

rpn> 8 show
  8
rpn> inv
  0.125

The pow operation raises to the power:

rpn> 3 4 show
  3
  4
rpn> pow
  81

The sqrt operation finds the square root:

rpn> 100 show
  100
rpn> sqrt
  10

The sum operation sums all values on the stack:

rpn> 1 2 3 4 5 show
  1
  2
  3
  4
  5
rpn> sum
  15

The prod operation multiplies all values on the stack:

rpn> 1 2 3 4 5 show
  1
  2
  3
  4
  5
rpn> prod
  120

Floating Point Error Handling

RPN uses big fractions for all operations, except when calculating square roots or other fractional powers, when it converts the arguments to floating point. In order to avoid floating point errors, it rounds all results to the nearest repeating decimal. Without this feature, the final result would be something like 2.000000000000000273:

rpn> 2 sqrt
  1.4142135623730951454746218587388284504413604736328125
rpn> dup mul
  2

Sequence Operations

The seq operation creates increasing or decreasing sequences of values, popping the start and end values from the stack and generating a step of 1.0 or -1.0:

rpn> 1 5 seq
┌ 1 ┐
│ 2 │
│ 3 │
│ 4 │
└ 5 ┘
rpn> 5 1 seq
┌ 5 ┐
│ 4 │
│ 3 │
│ 2 │
└ 1 ┘

The step operation does the same thing, but pops the start, step and end values; new values are created with the same meaning (plain, delta or time) as the start value:

rpn> 0 0.2 1 step
┌ 0   ┐
│ 0.2 │
│ 0.4 │
│ 0.6 │
│ 0.8 │
└ 1   ┘
rpn> 0 delta 3600 18000 step
┌       00.000 ┐
│ 01:00:00.000 │
│ 02:00:00.000 │
│ 03:00:00.000 │
│ 04:00:00.000 │
└ 05:00:00.000 ┘

The sort operation sorts values on the stack, treating "not a number" values as lower than everything else:

rpn> 4 2 1 0 div 3 5 1
    4
    2
  NaN
    3
    5
    1
rpn> sort
  NaN
    1
    2
    3
    4
    5

The rev operation reverses values on the stack:

rpn> 1 2 3 4 5 show
  1
  2
  3
  4
  5
rpn> rev
  5
  4
  3
  2
  1

The flat operation flattens all sequences on the stack:

rpn> 1 5 seq 6 8 seq
┌ 1 ┐
│ 2 │
│ 3 │
│ 4 │
└ 5 ┘
┌ 6 ┐
│ 7 │
└ 8 ┘
rpn> flat
  1
  2
  3
  4
  5
  6
  7
  8

Stack Operations for Sequences

If the values at the head of the stack are part of a sequence, operations which would otherwise apply to the entire stack (such as prod and sort) instead apply to that sequence only:

rpn> 11 10 5 4 3 2 1 show
  11
  10
   5
   4
   3
   2
   1
rpn> sort
   1
   2
   3
   4
   5
  10
  11
rpn> prod
  13200
rpn> 11 10 5 1 seq show
  11
  10
┌  5 ┐
│  4 │
│  3 │
│  2 │
└  1 ┘
rpn> sort
  11
  10
┌  1 ┐
│  2 │
│  3 │
│  4 │
└  5 ┘
rpn> prod
   11
   10
  120

Bitwise Operations

The and operation performs a bitwise AND on all bits:

rpn> 0xffff 0xff00ff hex
  0x0000ffff
  0x00ff00ff
rpn> and
  0x000000ff

The or operation performs a bitwise OR on all bits:

rpn> 0xffff 0xff00ff hex
  0x0000ffff
  0x00ff00ff
rpn> or
  0x00ffffff

The xor operation performs a bitwise XOR on all bits:

rpn> 0xffff 0xff00ff hex
  0x0000ffff
  0x00ff00ff
rpn> xor
  0x00ffff00

The shl operation shifts left, i.e. multiplies by a power of 2:

rpn> 0xff00 hex
  0x0000ff00
rpn> 8 shl
  0x00ff0000

The shr operation shifts right, i.e. divides by a power of 2:

rpn> 0xff00 hex
  0x0000ff00
rpn> 8 shr
  0x000000ff

Time Operations

The now command gets the current time, showing times in UTC:

rpn> now
  2025-03-31T12:34:56.789Z

The plain command converts to an integer or fractional value:

rpn> now
  2025-03-31T12:34:56.789Z
rpn> plain
  1743424496.789

The delta command converts to a delta value, optionally showing days, hours, minutes, seconds and milliseconds:

rpn> 86399 show
  86399
rpn> delta
  23:59:59.000

The time command converts to a time value, showing times in UTC:

rpn> 1709294400 show
  1709294400
rpn> time
  2024-03-01T12:00:00.000Z

Delta values can be added to or subtracted from times:

rpn> 1709294400 time 86400 delta
  2024-03-01T12:00:00.000Z
           1T00:00:00.000
rpn> sub
  2024-02-29T12:00:00.000Z

One time value can be subtracted from another:

rpn> 1709294400 time 1709208000 time
  2024-03-01T12:00:00.000Z
  2024-02-29T12:00:00.000Z
rpn> sub
  1T00:00:00.000

Unit Operations

Measurement units can be applied to values, in various categories:

  • Time (second, minute, hour, day, week, month, year). Note, month and year are defined as 30 and 365.25 days for this purpose.
  • Length (metre, inch, foot, yard, mile).
  • Area (square unit, hectare, acre).
  • Volume (cubic unit, litre, teaspoon, tablespoon, fluid ounce, cup, pint, quart, gallon, barrel) (UK and US versions).
  • Speed (distance over time, speed of sound in air at sea level, speed of light in vacuum).
  • Mass (gram, ounce, pound, stone, ton).
  • Temperature (Kelvin, Celsius, Fahrenheit, Rankine).
  • Data (byte, bit).

SI and related units can be specified by name or symbol (e.g. second or s, metre or m) with optional SI prefixes (e.g. millisecond or ms, kilometre or km). The same applies to byte units, but only multiplying prefixes are allowed (e.g. kilobyte or kB). International units can be specified by name only (e.g. mile, acre).

Plain values can be cast to specific units, and unit values are converted to equivalent units:

rpn> 37 celsius
  37 C
rpn> fahrenheit
  98.6 F
rpn> 1 light
  1 light
rpn> m/s sep
  299,792,458 m/s

All equivalent units can be added or subtracted, and RHS values are converted to LHS units. All equivalent units can be divided, and results are stripped of their units, leaving plain values:

rpn> 1 foot 6 inch
  1 foot
  6 inch
rpn> add
  1.5 foot
rpn> 1 mile 1 foot
  1 mile
  1 foot
rpn> div
  5280

Some non-equivalent units can also be multiplied or divided, for area, volume and speed values:

rpn> 70 mile/hour 30 minute
  70 mile/hour
  30 minute
rpn> mul
  35 mile
rpn> 144 inch^2 1 foot
  144 inch^2
    1 foot
rpn> div
  12 inch

Available units and prefixes can be shown with the units command:

rpn> units
  Prefix units:
    Q    quetta       10^30
    R    ronna        10^27
    Y    yotta        10^24
    Z    zetta        10^21
    E    exa          10^18
    P    peta         10^15
    T    tera         10^12
    G    giga         10^9
    M    mega         10^6
    k    kilo         10^3
    h    hecto        10^2
    da   deca         10
    -    -            1
    d    deci         10^-1
    c    centi        10^-2
    m    milli        10^-3
    u    micro        10^-6
    n    nano         10^-9
    p    pico         10^-12
    f    femto        10^-15
    a    atto         10^-18
    z    zepto        10^-21
    y    yocto        10^-24
    r    ronto        10^-27
    q    quecto       10^-30
  Time units:
    s    second
         minute
         hour
         day
         week
         month
         year
  Length units:
    m    metre
         inch
         foot
         yard
         mile
  Area units:
    m^2  square-metre (and other square-length units)
         hectare
         acre
  Volume units:
    m^3  cubic-metre (and other cubic-length units)
    l    litre
         tsp
         tbsp
         floz
         pint
         quart
         gallon
         barrel
         ustsp
         ustbsp
         usfloz
         uscup
         uspint
         usquart
         usgallon
         usbarrel
  Speed units:
    m/s  metre/second (and other length/time units)
         mach
         light
  Mass units:
    g    gram
         ounce
         pound
         stone
         ton
  Temperature units:
    K    kelvin
    C    celsius
    F    fahrenheit
    R    rankine
  Data units:
    B    byte
         bit

Formatting Commands

The dec and hex commands format values as decimal and hexadecimal:

rpn> 2 32 pow hex
  0x0000000100000000
rpn> dec
  4294967296

The sep and nosep commands show and hide separators for decimal and hexadecimal:

rpn> 2 32 pow hex sep
  0x,00000001,00000000
rpn> dec
  4,294,967,296

The dp and nodp commands set and cancel fixed precision for decimal:

rpn> 2 sqrt
  1.4142135623730951454746218587388284504413604736328125
rpn> 0 dp
  1
rpn> 3 dp
  1.414
rpn> 6 dp
  1.414214
rpn> nodp
  1.4142135623730951454746218587388284504413604736328125

Stack Commands

The clear command removes all values from the stack:

rpn> 1 23 456 show
    1
   23
  456
rpn> clear

The pop command removes a value from the stack:

rpn> 1 23 456 show
    1
   23
  456
rpn> pop
   1
  23

The dup command duplicates a value on the stack:

rpn> 1 23 456 show
    1
   23
  456
rpn> dup
    1
   23
  456
  456

The swap command swaps two values on the stack:

rpn> 1 23 456 show
    1
   23
  456
rpn> swap
    1
  456
   23

The cut and copy commands store a value from the stack in the internal clipboard. The paste command copies that value back to the stack:

rpn> 1 23 show
   1
  23
rpn> copy
rpn> 456 show
    1
   23
  456
rpn> paste
    1
   23
  456
   23

History Commands

The undo and redo commands undo the last operation, and redo the next operation in the history:

rpn> 1 23 456 show
    1
   23
  456
rpn> prod
  10488
rpn> undo
    1
   23
  456
rpn> undo
rpn> undo
  Start of undo history
rpn> redo
    1
   23
  456
rpn> redo
  10488
rpn> redo
  End of undo history

The hist command shows all undo history:

rpn> 1 23 456 show
    1
   23
  456
rpn> prod
  10488
rpn> undo
    1
   23
  456
rpn> hist
  1 23 456 <==
  prod

General Directives

The import directive imports values and operations from a text file; the export directive exports values to a text file. The following creates a file containing the result of the multiplication:

rpn> import params.txt
  6
  7
rpn> mul
  42
rpn> export result.txt

The set or = directive sets a named variable to the most recent entry on the stack:

rpn> 36 sqrt = x
  6 = x
rpn> 49 sqrt = y
  6 = x
  7 = y
rpn> x y mul
   6 = x
   7 = y
  42
rpn> set xy
   6 = x
   7 = y
  42 = xy

Multiple variables can be set on the same line, and variables can be listed with the set or = directive by itself:

rpn> 1 = one 2 = two 3 = three 4 = four 5 = five 6 7 8
  1 = one
  2 = two
  3 = three
  4 = four
  5 = five
  6
  7
  8
rpn> set
  5 = five
  4 = four
  1 = one
  3 = three
  2 = two

The define directive defines a custom function for subsequent use:

rpn> define cube 3 pow
rpn> 2 cube
  8

The define directive with a function name but no body undefines the function. The directive with no function name lists defined functions, with hints on expected inputs and outputs, and this information is also included in the inline help:

rpn> define cube 3 pow
rpn> define percent 100 div
rpn> define fubar 0 div
rpn> define fubar
rpn> define
  Defined functions:
      N  cube    N    Function "3 pow"
      N  percent N    Function "100 div"

The apply directive applies the same operation (or sequence of operations) to each value on the stack:

rpn> 1 2 3 4 5 show
  1
  2
  3
  4
  5
rpn> apply 3 pow
    1
    8
   27
   64
  125

Only operations which pop one input and push one output are allowed:

rpn> 1 2 3 4 5 show
  1
  2
  3
  4
  5
rpn> apply add
  Unsupported apply: N N to N

When operations are applied to multiple values, a temporary stack is created for each value, so each result is calculated independently. The temporary stack may contain multiple intermediate values or sequences, as long as they reduce down to a single value at the end. This allows us to (for example) find the factorial of each value on the stack:

rpn> define fact 1 seq prod
rpn> 1 5 seq flat
  1
  2
  3
  4
  5
rpn> apply fact
    1
    2
    6
   24
  120

Comments

It is possible to add a comment to any entered value, or the result of a calculation. Comments remain attached to their values until replaced, and are copied to duplicated values:

rpn> 6 7
rpn> mul # the answer
  42 # the answer
rpn> dup
  42 # the answer
  42 # the answer
Commit count: 0

cargo fmt