https://github.com/iwdgo/postfixcalculator
Reverse Polish Notation calculator using various techniques
https://github.com/iwdgo/postfixcalculator
benchmarks emulating-stack go golang rpn rpn-operators turing-machine
Last synced: 4 months ago
JSON representation
Reverse Polish Notation calculator using various techniques
- Host: GitHub
- URL: https://github.com/iwdgo/postfixcalculator
- Owner: iwdgo
- License: bsd-2-clause
- Created: 2018-03-15T13:37:05.000Z (almost 8 years ago)
- Default Branch: master
- Last Pushed: 2024-10-07T06:12:06.000Z (over 1 year ago)
- Last Synced: 2025-07-22T04:50:44.079Z (6 months ago)
- Topics: benchmarks, emulating-stack, go, golang, rpn, rpn-operators, turing-machine
- Language: Go
- Homepage: https://pkg.go.dev/github.com/iwdgo/postfixcalculator
- Size: 112 KB
- Stars: 0
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
[](https://pkg.go.dev/github.com/iwdgo/postfixcalculator)
[](https://goreportcard.com/report/github.com/iwdgo/postfixcalculator)
[](https://codecov.io/gh/iWdGo/postfixcalculator)
[](https://ci.appveyor.com/project/iWdGo/postfixcalculator)
[](https://github.com/iwdgo/postfixcalculator/actions/workflows/go.yml)
# Reverse Polish Notation calculator
Several solutions to this well-known problem show dramatic differences depending on the approach.
A Turing machine emulation rivals the method of reference using a stack emulation.
## Features
All solutions support :
- float numbers
- arithmetic operators written + - * /
- binary operator ^ (exponent)
- unary operator `sqrt`
Input is a string where elements are spaced. Calculation panics on invalid values and operators.
Float values are parsed as 64 bits.
The original expression is used to store values and edited. When one result is left,
calculation is complete and the result is returned.
## Solutions
- [slice editing](https://pkg.go.dev/github.com/iwdgo/postfixcalculator/stack)
- [emulating stack using the slice](https://pkg.go.dev/github.com/iwdgo/postfixcalculator/emulatingstack)
- [using a stack-like struct](https://pkg.go.dev/github.com/iwdgo/postfixcalculator/emulatingstack)
- [using string to hold a list of operators in two loops](https://pkg.go.dev/github.com/iwdgo/postfixcalculator/operatorslist)
- [using string to hold a list of operators in one loop](https://pkg.go.dev/github.com/iwdgo/postfixcalculator/operatorsnofields)
- Turing machine:
- [slow](https://pkg.go.dev/github.com/iwdgo/postfixcalculator/slowturingmachine)
- [fast](https://pkg.go.dev/github.com/iwdgo/postfixcalculator/turingmachine)
## How to
There are examples in every package. A first use that prints 4 could be:
```
package main
import "github.com/iwdgo/postfixcalculator/turingmachine"
func main() {
println(turingmachine.RPNTuringMachine("2 2 +"))
}
```
## Results
- Emulating the stack is the most efficient classic method.
- Using a `struct` from an existing package divides performance by 2.
- Adding slice editing slows performance by a factor of 3.
- The worst occurs when all elements of the expression and its results are in one slice as
conversion to and from numbers is an expensive operation.
Slice is the underlying type of string. So string editing will probably not improve if not worsen
as a string is read-only and could be copied many times during the process.
## Optimum
Turing machine beats the stack emulation only if the `for` loop is re-used instead of re-creating it.
Performance degrades dramatically when using a `while` form with increment inside the loop to follow usual
practice.
Exploring the slice of strings containing all terms of the expression efficiently is executed by rewinding the band.
Initializing and exiting without finishing a `for` loop using `range` is costly.
## Evaluation
To run tests: `>go test ./...`
To run benchmarks `>go test -bench=. ./...`
```
go version go1.19.4 windows/amd64
$ go test -bench=. -benchtime=5s ./... | grep Benchmark
BenchmarkRPNEmulatingStack-4 5973022 1006 ns/op
BenchmarkRPN-4 963788 5985 ns/op
BenchmarkRPNOperatorsList-4 1248453 4903 ns/op
BenchmarkRPNOperatorsNoFields-4 1488712 3969 ns/op
BenchmarkRPNSlowTuringMachine-4 3583735 1690 ns/op
BenchmarkRPNStack-4 3169281 1886 ns/op
BenchmarkRPNTuringMachine-4 6172328 981.0 ns/op
```