Created
October 15, 2021 10:05
-
-
Save DreamVB/94d0e42233f552da7e10749e8598a50b to your computer and use it in GitHub Desktop.
rpn calculator class with variables and functions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Windows.Forms; | |
using DreamVB.RPNCalulator; | |
namespace RPNTest | |
{ | |
public partial class Form1 : Form | |
{ | |
public Form1() | |
{ | |
InitializeComponent(); | |
} | |
private void button1_Click(object sender, EventArgs e) | |
{ | |
clsRpn calc = new clsRpn(); | |
calc.SetVariable("ten", 10); | |
MessageBox.Show(calc.Eval("%ten 50 +").ToString()); | |
MessageBox.Show(calc.Eval("5 5 * 5 +").ToString()); | |
MessageBox.Show(calc.Eval("#PI").ToString()); | |
MessageBox.Show(calc.Eval("#e").ToString()); | |
MessageBox.Show(calc.Eval("9 sqr").ToString()); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace RPNCalulator | |
{ | |
public class clsRpn | |
{ | |
private Dictionary<string, double> Vars = new Dictionary<string, double>(); | |
private bool IsOperator(char c) | |
{ | |
bool isOp = false; | |
switch (c) | |
{ | |
case '+': | |
isOp = true; | |
break; | |
case '-': | |
isOp = true; | |
break; | |
case '/': | |
isOp = true; | |
break; | |
case '*': | |
isOp = true; | |
break; | |
case '^': | |
isOp = true; | |
break; | |
} | |
return isOp; | |
} | |
public void SetVariable(string vName, double value) | |
{ | |
if (Vars.ContainsKey(vName)) | |
{ | |
Vars[vName] = value; | |
} | |
else | |
{ | |
Vars.Add(vName, value); | |
} | |
} | |
public bool VariableExists(string vName) | |
{ | |
return Vars.ContainsKey(vName); | |
} | |
public double Eval(string expression) | |
{ | |
Stack<double> stk = new Stack<double>(); | |
double number = 0; | |
string token = string.Empty; | |
string[] _parts = expression.Split(' '); | |
int x = 0; | |
//Used for calulations | |
double d1 = 0; | |
double d2 = 0; | |
while (x < _parts.Length) | |
{ | |
token = _parts[x].Trim(); | |
if (token.Length > 0) | |
{ | |
if (double.TryParse(token, out number)) | |
{ | |
stk.Push(double.Parse(token)); | |
} | |
else if (IsOperator(token[0])) | |
{ | |
//Check stack count | |
if (!(stk.Count >= 2)) | |
{ | |
throw new Exception("Stack Underflow."); | |
} | |
else | |
{ | |
//Pop off the values on the stack | |
d2 = stk.Pop(); | |
d1 = stk.Pop(); | |
switch (token[0]) | |
{ | |
case '+': | |
stk.Push(d1 + d2); | |
break; | |
case '-': | |
stk.Push(d1 - d2); | |
break; | |
case '/': | |
if (d2 == 0.0) | |
{ | |
throw new Exception("Divisn By Zero."); | |
} | |
else | |
{ | |
stk.Push(d1 / d2); | |
} | |
break; | |
case '*': | |
stk.Push(d1 * d2); | |
break; | |
case '^': | |
stk.Push(Math.Pow(d1, d2)); | |
break; | |
} | |
} | |
} | |
//Check for variable | |
else if (token.StartsWith("%")) | |
{ | |
//Remove % from the left side | |
token = token.Remove(0, 1); | |
//Check if variable found | |
if (!VariableExists(token)) | |
{ | |
throw new Exception("Variable Not Found."); | |
} | |
else | |
{ | |
//Push variable value | |
stk.Push(Vars[token]); | |
} | |
} | |
//Check for consts | |
else if (token.StartsWith("#")) | |
{ | |
//Remove const sign | |
token = token.Remove(0,1).ToUpper(); | |
switch (token) | |
{ | |
case "PI": | |
stk.Push(Math.PI); | |
break; | |
case "E": | |
stk.Push(Math.E); | |
break; | |
default: | |
throw new Exception("Unknown Const Token."); | |
} | |
}else | |
{ | |
//Process in-built functions | |
switch (token.ToUpper()) | |
{ | |
case "ABS": | |
stk.Push(Math.Abs(stk.Pop())); | |
break; | |
case "CEIL": | |
stk.Push(Math.Ceiling(stk.Pop())); | |
break; | |
case "EXP": | |
stk.Push(Math.Exp(stk.Pop())); | |
break; | |
case "POW": | |
d2 = stk.Pop(); | |
d1 = stk.Pop(); | |
stk.Push(Math.Pow(d1, d2)); | |
break; | |
case "SIN": | |
stk.Push(Math.Sin(stk.Pop() / (180.0 / Math.PI))); | |
break; | |
case "COS": | |
stk.Push(Math.Cos(stk.Pop() / (180.0 / Math.PI))); | |
break; | |
case "LN": | |
stk.Push(Math.Log(stk.Pop())); | |
break; | |
case "SQRT": | |
stk.Push(Math.Sqrt(stk.Pop())); | |
break; | |
case "FLOOR": | |
stk.Push(Math.Floor(stk.Pop())); | |
break; | |
case "TAN": | |
stk.Push(Math.Tan(stk.Pop() / (180.0 / Math.PI))); | |
break; | |
case "SQR": | |
d1 = stk.Pop(); | |
//Calc sqr root | |
for (int y = 1; y <= d1; y++) | |
{ | |
d2 = (y * d1); | |
} | |
//Push value on stack | |
stk.Push(d2); | |
break; | |
case "MIN": | |
d2 = stk.Pop(); | |
d1 = stk.Pop(); | |
stk.Push(Math.Min(d1, d2)); | |
break; | |
case "MAX": | |
d2 = stk.Pop(); | |
d1 = stk.Pop(); | |
stk.Push(Math.Max(d1, d2)); | |
break; | |
case "INT": | |
stk.Push(Convert.ToInt32(stk.Pop())); | |
break; | |
case "LOG": | |
stk.Push(Math.Log(stk.Pop())); | |
break; | |
default: | |
throw new Exception("Unknown Function Token."); | |
} | |
} | |
} | |
x++; | |
} | |
try | |
{ | |
return stk.Pop(); | |
} | |
catch(Exception ex) | |
{ | |
throw new Exception(ex.Message); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment