Implementing order of operations for a Java calculator.
How would I go about implementing order of operations for a calculator program that takes input from its GUI and stores it for further processing in the form of Strings?
ETA: I accidentally hit the "Submit thread" button; I will be posting code shortly.
Re: Implementing order of operations for a Java calculator.
I already have some code that implements order of operations without algebraic grouping (i.e., parentheses/bracket):
Code Java:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Stack;
import javax.swing.JTextField;
import java.lang.*;
public class ArithmeticListener implements ActionListener
{
boolean optPsh = false;
boolean pntPsh = false;
double fOpd;
double sOpd;
double res;
String ariStr = "";
String digStr = "";
String pntStr = "";
String opdStr = "";
String curOpdStr = "";
String prvOpdStr = "";
String curOptStr = "";
String prvOptStr = "";
Stack<String> expStck = new Stack<String> ();
Stack<String> opdStck = new Stack<String> ();
Stack<String> optStck = new Stack<String> ();
JTextField scrn;
ArithmeticListener(CalculatorGUI calGUI)
{
scrn = calGUI.cs.screen;
}
public void actionPerformed(ActionEvent ae)
{
ariStr = ae.getActionCommand();
opdStr = scrn.getText();
/*Operand entry omitted for brevity*/
if (ariStr.equals("+") || ariStr.equals("-"))
{
curOptStr = ariStr;
curOpdStr = scrn.getText();
optPsh = true;
pntPsh = false;
if (opdStck.empty() && optStck.empty())
{
opdStck.push(curOpdStr);
optStck.push(curOptStr);
}
else
{
if (opdStck.size() == 1 && optStck.size() == 1)
{
prvOptStr = optStck.pop();
prvOpdStr = opdStck.pop();
sOpd = Double.parseDouble(curOpdStr);
fOpd = Double.parseDouble(prvOpdStr);
if (prvOptStr.equals("+"))
{
res = fOpd + sOpd;
}
else if (prvOptStr.equals("-"))
{
res = fOpd - sOpd;
}
else if (prvOptStr.equals("*"))
{
res = fOpd * sOpd;
}
else if (prvOptStr.equals("/"))
{
res = fOpd / sOpd;
}
opdStck.push(res + "");
optStck.push(curOptStr);
scrn.setText(res + "");
}
else
{
while (opdStck.size() > 0 && optStck.size() > 0)
{
prvOptStr = optStck.pop();
prvOpdStr = opdStck.pop();
sOpd = Double.parseDouble(curOpdStr);
fOpd = Double.parseDouble(prvOpdStr);
if (prvOptStr.equals("+"))
{
res = fOpd + sOpd;
}
else if (prvOptStr.equals("-"))
{
res = fOpd - sOpd;
}
else if (prvOptStr.equals("*"))
{
res = fOpd * sOpd;
}
else if (prvOptStr.equals("/"))
{
res = fOpd / sOpd;
}
curOpdStr = (res + "");
for (String s : opdStck)
{
System.out.print(s);
}
System.out.println();
for (String s : optStck)
{
System.out.print(s);
}
System.out.println();
System.out.println();
}
opdStck.push(res + "");
optStck.push(curOptStr);
scrn.setText(res + "");
}
}
}
else if (ariStr.equals("*")|| ariStr.equals("/"))
{
curOptStr = ariStr;
curOpdStr = scrn.getText();
optPsh = true;
pntPsh = false;
if (opdStck.empty() && optStck.empty())
{
opdStck.push(curOpdStr);
optStck.push(curOptStr);
}
else
{
if (opdStck.size() == 1 && optStck.size() == 1)
{
prvOptStr = optStck.pop();
prvOpdStr = opdStck.pop();
if (prvOptStr.equals("+") || prvOptStr.equals("-"))
{
opdStck.push(prvOpdStr);
optStck.push(prvOptStr);
opdStck.push(curOpdStr);
optStck.push(curOptStr);
}
else if (prvOptStr.equals("*") || prvOptStr.equals("/"))
{
sOpd = Double.parseDouble(curOpdStr);
fOpd = Double.parseDouble(prvOpdStr);
if (prvOptStr.equals("*"))
{
res = fOpd * sOpd;
}
else if (prvOptStr.equals("/"))
{
res = fOpd / sOpd;
}
opdStck.push(res + "");
}
}
else
{
opdStck.push(curOpdStr);
optStck.push(curOptStr);
}
}
}
else if (ariStr.equals("="))
{
while (opdStck.size() > 0 && optStck.size() > 0)
{
prvOptStr = optStck.pop();
prvOpdStr = opdStck.pop();
sOpd = Double.parseDouble(curOpdStr);
fOpd = Double.parseDouble(prvOpdStr);
if (prvOptStr.equals("+"))
{
res = fOpd + sOpd;
}
else if (prvOptStr.equals("-"))
{
res = fOpd - sOpd;
}
else if (prvOptStr.equals("*"))
{
res = fOpd * sOpd;
}
else if (prvOptStr.equals("/"))
{
res = fOpd / sOpd;
}
curOpdStr = (res + "");
}
opdStck.push(res + "");
optStck.push(curOptStr);
scrn.setText(res + "");
}
else if (ariStr.equals("C"))
{
while (!opdStck.empty() && !optStck.empty())
{
optStck.pop();
opdStck.pop();
}
optPsh = false;
pntPsh = false;
fOpd = 0;
sOpd = 0;
res = 0;
ariStr = "";
digStr = "";
opdStr = "";
curOpdStr = "";
prvOpdStr = "";
curOptStr = "";
prvOptStr = "";
scrn.setText("0");
}
}
}
Now, the way I see things, I have two options:
- Add a parenthesis Stack to the current method
- Get rid of the operator Stack and the operand Stack and just have an expression Stack
The latter option seems to be more straightforward because I don't have to come up with a way to "sync" up to the Stacks in order to keep track of where the parentheses are entered.
The problem that I am currently having, though, is that, when I enter an open parenthesis, the previous operand is pushed onto the Stack as well. I think that this is happening because I have misplaced a call to the screen's getText() method and the operand text on the screen is getting pushed onto the the Stack
with the open parenthesis. However, I cannot justify this thought when I look at the code:
Code Java:
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
public class Dummy implements ActionListener
{
boolean optPsh = false;
boolean pntPsh = false;
int numOpnPar;
double fOpd;
double sOpd;
double res;
String ariStr = "";
String digStr = "";
String pntStr = "";
String opdStr = "";
String curOpdStr = "";
String prvOpdStr = "";
String curOptStr = "";
String prvOptStr = "";
Stack<String> expStck = new Stack<String> ();
Stack<String> opdStck = new Stack<String> ();
Stack<String> optStck = new Stack<String> ();
JTextField scrn;
Dummy(CalculatorGUI cg)
{
scrn = cg.cs.screen;
}
public void actionPerformed(ActionEvent ae)
{
ariStr = ae.getActionCommand();
char [] ariChrArr = ariStr.toCharArray();
opdStr = scrn.getText();
Character ariChr = ariChrArr[0];
System.out.println("ariChr: " + ariChr);
if (!ariStr.equals("C") && !ariStr.equals("CE"))
{
if (isOpd(ariChr))
{
System.out.println("Operand Character");
if(!optPsh)
{
if (!pntPsh)
{
if (opdStr.equals("0"))
{
if (Character.isDigit(ariChr))
{
opdStr = ariStr;
}
else if (ariStr.equals("."))
{
opdStr = "0" + ariStr;
pntPsh = true;
}
}
else
{
if (Character.isDigit(ariChr))
{
opdStr += ariStr;
}
else if (ariStr.equals("."))
{
opdStr += ariStr;
pntPsh = true;
}
}
}
else
{
if (Character.isDigit(ariChr))
{
opdStr += ariStr;
}
else if (ariStr.equals("."))
{
opdStr += ariStr;
pntPsh = true;
}
}
}
else
{
if (!pntPsh)
{
if (opdStr.equals("0"))
{
if (Character.isDigit(ariChr))
{
opdStr = ariStr;
}
else if (ariStr.equals("."))
{
opdStr = "0" + ariStr;
pntPsh = true;
}
}
else
{
if (Character.isDigit(ariChr))
{
opdStr = ariStr;
}
else if (ariStr.equals("."))
{
opdStr = "0" + ariStr;
pntPsh = true;
}
}
}
optPsh = false;
}
scrn.setText(opdStr);
ariStr = "";
}
else
{
curOptStr = ariChr.toString();
optPsh = true;
if (curOptStr.equals("("))
{
expStck.push(curOptStr);
}
if (curOptStr.equals(")"))
{
expStck.push(curOptStr);
}
else
{
curOpdStr = scrn.getText();
expStck.push(curOpdStr);
expStck.push(curOptStr);
}
System.out.print("expStck: ");
prntExprStck(expStck);
curOpdStr = "";
curOptStr = "";
}
}
else if (ariStr.equals("C"))
{
while (!expStck.empty())
{
expStck.pop();
}
scrn.setText("0");
optPsh = false;
pntPsh = false;
fOpd = 0;
sOpd = 0;
res = 0;
ariStr = "";
digStr = "";
pntStr = "";
opdStr = "";
curOpdStr = "";
prvOpdStr = "";
curOptStr = "";
prvOptStr = "";
}
else if (ariStr.equals("CE"))
{
scrn.setText("0");
}
}
boolean isOpd(Character chr)
{
if (Character.isDigit(chr) || chr == '.')
{
return true;
}
else
{
return false;
}
}
}
Am I completely missing something else I have not mentioned?
Re: Implementing order of operations for a Java calculator.
Since a lot of your code is missing, the only thing I can suggest is to add some print statements to your code to display variables as they change and to trace execution flow.