calculator --- using more than 2 operands?


DevX Home    Today's Headlines   Articles Archive   Tip Bank   Forums   

Results 1 to 13 of 13

Thread: calculator --- using more than 2 operands?

  1. #1
    Join Date
    Jan 2005
    Posts
    8

    calculator --- using more than 2 operands?

    I have this calculator I've been working on in my free time. It works pretty good, except for the fact you can only have two operands..

    Could someone take a look at it and tell me how I could make it so I can have more than two operands?

    like this:

    1-2+3/4*5

    Right now I can only do this:

    1+2 (or any operator)

    Here is my code:

    Code:
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    
    public class Calculator extends JFrame implements ActionListener
    {
    	JButton[] btnNums;
    	JButton btnBack;
    	JButton btnClear;
    	JButton btnCalculate;
    	String[] strNames;
    	String strOperand1;
    	String strOperand2;
    	Boolean wasClicked;
    	String answer;
    	double dd;
    
    	final String STR_MULTIPLY = "MULTIPLY";
    	final String STR_DIVIDE = "DIVIDE";
    	final String STR_ADD = "ADD";
    	final String STR_SUBTRACT = "SUBTRACT";
    
    	String whichOperator;
    	
    	
    	JTextField txtDisplay;
    	
    	public Calculator()
    	{
    		Container content = getContentPane();
    		setSize(210,250);
    		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		
    		
    		/*  construct a JPanel and the textfield that 
    		 *  will show the inputed values and outputed 
    		 *  results
    		 */
    		JPanel jpDisplay = new JPanel();
    		jpDisplay.setLayout(new BorderLayout());
    		txtDisplay = new JTextField(15);
    		txtDisplay.setHorizontalAlignment(JTextField.RIGHT);
    		jpDisplay.add(txtDisplay);
    		
    		/*  contstruct a JPanel that will contain a back
    		 *  button and a clear button.
    		 */
    		JPanel jpRow2 = new JPanel();
    		btnBack = new JButton("Backspace");
    		btnBack.addActionListener(this);
    		btnClear = new JButton("Clear");
    		btnClear.addActionListener(this);
    		btnClear.addActionListener(this);
    		jpRow2.add(btnBack);
    		jpRow2.add(btnClear);
    		
    		/*  construct a string array with all the names of the
    		 *  buttons, then in a for loop create the new buttons
    		 *  and add their name and an actionListener to them.
    		 */
    		String[] strNames = {"7","8", "9","/", "4", "5", "6","*", "1",
    					   "2", "3","+", "0", "+/-", ".", "-"};
    		btnNums = new JButton[16];
    		JPanel jpButtons = new JPanel();
    		jpButtons.setLayout(new GridLayout(4,4));
    		
    		  for (int i = 0; i < 16; i++)
    		  {
    			  btnNums[i] = new JButton(strNames[i]);
    			  btnNums[i].addActionListener(this);
    			  jpButtons.add(btnNums[i]);
    		  }
    		  
    		  /*  construct the final JPanel and add a 
    		   *  calculate button to it.
    		   */
    		  JPanel jpLastRow = new JPanel();
    		  btnCalculate = new JButton("Calculate");
    		  btnCalculate.addActionListener(this);
    		  jpLastRow.add(btnCalculate);
    		  
    		  
    		  //make wasClicked have a default value of false
    		  wasClicked = false;
    		  
    		  /*  set the contentPane and create the layout
    		   *  add the panels to the container
    		   */
    		  setContentPane(content);
    		  setLayout(new FlowLayout());
    		  setResizable(false);
    		  content.add(jpDisplay, BorderLayout.NORTH);
    		  content.add(jpRow2);
    		  content.add(jpButtons);
    		  content.add(jpLastRow);
    		  setTitle("Mini Calculator");
    		  setVisible(true); 
    		  
    	}
    	
     
    	public void actionPerformed(ActionEvent ae)
    	{
    		// if any of the array buttons was clicked append the button's text
    		for (int i =0; i < 16; i++)
    		{
    			if (ae.getSource() == btnNums[i])
    			{
    				txtDisplay.setText(txtDisplay.getText()
    						+ btnNums[i].getText());
    				
    			}
    		}
    		
    		
    		/*  if the backspace button was clicked, then create substring
    		 *  to to subtract the farthest character to the right
    		 */
    		if (ae.getSource() == btnBack)
    		{
    			String strAll = txtDisplay.getText();
    			int length = strAll.length();
    			String strShowThis = strAll.substring(0,length - 1);
    			txtDisplay.setText(strShowThis);
    		}
    			else if (ae.getSource() == btnClear)
    			{
    				txtDisplay.setText(null);
    			}	
    			else if (ae.getSource() == btnCalculate)
    			{
    				String strText = txtDisplay.getText();
    				try 
    				{
    					int equation = Integer.parseInt(strText);
    					txtDisplay.setText("" + equation);
    				}
    				catch (ArithmeticException aee)
    				{
    					aee.printStackTrace();
    		 	 }
    			
    			}
    			
    			/*  start the process of finding which operator was 
    			 *  chosen, and the process the equation in a new 
    			 *  method
    			 */
    			 
    			 if (ae.getSource() == btnNums[3])
    			 {
    				 processDivide();
    			 }
    			 else if (ae.getSource() == btnNums[7])
    			 {
    				 processMultiply();
    			 }
    			 else if (ae.getSource() == btnNums[11])
    			 {
    				 processAdd();
    			 }
    			 else if (ae.getSource() == btnNums[13])
    			 {
    				processPosOrNeg();
    			 }
    			 else if (ae.getSource() == btnNums[15])
    			 {
    				 processSubtract();
    			 }
    			 else
    			 {
    			 }
    
    		// and finally process the calculation
    		if (ae.getSource() == btnCalculate)
    		{
    			processCalc();
    		}
    		else
    		{
    		}
    	}
    	
    	public void processDivide()
    	{
    		whichOperator = STR_DIVIDE;
    		strOperand1 = txtDisplay.getText();
    		int x = strOperand1.length();
    		String s = strOperand1.substring(0, x - 1);
    		dd = Double.parseDouble(s);
    		txtDisplay.setText(null);
    	}
    	public void processMultiply()
    	{
    		whichOperator = STR_MULTIPLY;
    		strOperand1 = txtDisplay.getText();
    		int x = strOperand1.length();
    		String s = strOperand1.substring(0, x - 1);
    		dd = Double.parseDouble(s);
    		txtDisplay.setText(null);
    	}
    	public void processAdd()
    	{
    		whichOperator = STR_ADD;
    		strOperand1 = txtDisplay.getText();
    		int x = strOperand1.length();
    		System.out.println("variable x = " + x);
    		String s = strOperand1.substring(0, x - 1);
    		System.out.println("variable s = " + s);
    		dd = Double.parseDouble(s);
    		System.out.println("variable d = " + dd);
    		txtDisplay.setText(null);
    	}
    	public void processPosOrNeg()
    	{
    	}
    	public void processSubtract()
    	{
    		whichOperator = STR_SUBTRACT;
    		strOperand1 = txtDisplay.getText();
    		int x = strOperand1.length();
    		String s = strOperand1.substring(0, x - 1);
    		dd = Double.parseDouble(s);
    		txtDisplay.setText(null);
    	}
    
    	public void processCalc()
    	{
    		strOperand2 = txtDisplay.getText();
    		int x = strOperand2.length();
    		String s = strOperand2.substring(0, x);
    		double d = Double.parseDouble(s);
    		
    		if (whichOperator == STR_SUBTRACT)
    		{
    			double a = dd - d;
    			txtDisplay.setText(dd + "-" + d + " = " + a);
    		}
    		else if (whichOperator == STR_ADD)
    		{
    			double a = dd + d;
    			txtDisplay.setText(dd + "+" + d + " = " + a);
    		}
    		else if (whichOperator == STR_MULTIPLY)
    		{
    				double a = dd * d;
    			txtDisplay.setText(dd + "*" + d + " = " + a);
    		}
    		else if (whichOperator == STR_DIVIDE)
    		{
    				double a = dd / d;
    			txtDisplay.setText(dd + "/" + d + " = " + a);
    		}
    		else 
    		{
    		}
    	
    	}
    	
    	public static void main(String[] args)
    	{
    		Calculator calc = new Calculator();
    	}
    }

  2. #2
    Join Date
    Nov 2004
    Location
    Norway
    Posts
    1,560
    You are probably aware that this doesn't compile, no
    big deal though. I'll have a look
    eschew obfuscation

  3. #3
    Join Date
    Jan 2005
    Posts
    8
    compiles fine on my machine. Im using 1.5, so I guess it's probably your using something earlier than this?

  4. #4
    Join Date
    Nov 2004
    Location
    Norway
    Posts
    1,560
    Yes I'm using 1.4... something. I got two errors:

    // setLayout(new FlowLayout()); <---- error
    this.getContentPane().setLayout(new FlowLayout());

    and this:

    wasClicked = false; (Booleans in 1.4 have no operator overloading)
    eschew obfuscation

  5. #5
    Join Date
    Jan 2005
    Posts
    8
    Here is a more updated code..It gets rid of the wasClicked boolean object. You'll just have to change the layout manager so it will work.

  6. #6
    Join Date
    Jan 2005
    Posts
    8
    lol forgot the code:

    Code:
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    
    public class Calculator extends JFrame implements ActionListener
    {
    	JButton[] btnNums;
    	JButton btnBack;
    	JButton btnClear;
    	JButton btnCalculate;
    	String[] strNames;
    	String strOperand1;
    	String strOperand2;
    	Boolean wasClicked;
    	String answer;
    	double dd;
    
    	final String STR_MULTIPLY = "MULTIPLY";
    	final String STR_DIVIDE = "DIVIDE";
    	final String STR_ADD = "ADD";
    	final String STR_SUBTRACT = "SUBTRACT";
    
    	String whichOperator;
    	
    	
    	JTextField txtDisplay;
    	
    	public Calculator()
    	{
    		Container content = getContentPane();
    		setSize(210,250);
    		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		
    		
    		/*  construct a JPanel and the textfield that 
    		 *  will show the inputed values and outputed 
    		 *  results
    		 */
    		JPanel jpDisplay = new JPanel();
    		jpDisplay.setLayout(new BorderLayout());
    		txtDisplay = new JTextField(15);
    		txtDisplay.setHorizontalAlignment(JTextField.RIGHT);
    		jpDisplay.add(txtDisplay);
    		
    		/*  contstruct a JPanel that will contain a back
    		 *  button and a clear button.
    		 */
    		JPanel jpRow2 = new JPanel();
    		btnBack = new JButton("Backspace");
    		btnBack.addActionListener(this);
    		btnClear = new JButton("Clear");
    		btnClear.addActionListener(this);
    		btnClear.addActionListener(this);
    		jpRow2.add(btnBack);
    		jpRow2.add(btnClear);
    		
    		/*  construct a string array with all the names of the
    		 *  buttons, then in a for loop create the new buttons
    		 *  and add their name and an actionListener to them.
    		 */
    		String[] strNames = {"7","8", "9","/", "4", "5", "6","*", "1",
    					   "2", "3","+", "0", "+/-", ".", "-"};
    		btnNums = new JButton[16];
    		JPanel jpButtons = new JPanel();
    		jpButtons.setLayout(new GridLayout(4,4));
    		
    		  for (int i = 0; i < 16; i++)
    		  {
    			  btnNums[i] = new JButton(strNames[i]);
    			  btnNums[i].addActionListener(this);
    			  jpButtons.add(btnNums[i]);
    		  }
    		  
    		  /*  construct the final JPanel and add a 
    		   *  calculate button to it.
    		   */
    		  JPanel jpLastRow = new JPanel();
    		  btnCalculate = new JButton("Calculate");
    		  btnCalculate.addActionListener(this);
    		  jpLastRow.add(btnCalculate);
    		  
    		  
    		  //make wasClicked have a default value of false
    		  wasClicked = false;
    		  
    		  /*  set the contentPane and create the layout
    		   *  add the panels to the container
    		   */
    		  setContentPane(content);
    		  setLayout(new FlowLayout());
    		  setResizable(false);
    		  content.add(jpDisplay, BorderLayout.NORTH);
    		  content.add(jpRow2);
    		  content.add(jpButtons);
    		  content.add(jpLastRow);
    		  setTitle("Mini Calculator");
    		  setVisible(true); 
    		  
    	}
    	
     
    	public void actionPerformed(ActionEvent ae)
    	{
    		// if any of the array buttons was clicked append the button's text
    		for (int i =0; i < 16; i++)
    		{
    			if (ae.getSource() == btnNums[i])
    			{
    				txtDisplay.setText(txtDisplay.getText()
    						+ btnNums[i].getText());
    				
    			}
    		}
    		
    		
    		/*  if the backspace button was clicked, then create substring
    		 *  to to subtract the farthest character to the right
    		 */
    		if (ae.getSource() == btnBack)
    		{
    			String strAll = txtDisplay.getText();
    			int length = strAll.length();
    			String strShowThis = strAll.substring(0,length - 1);
    			txtDisplay.setText(strShowThis);
    		}
    			else if (ae.getSource() == btnClear)
    			{
    				txtDisplay.setText(null);
    			}	
    			else if (ae.getSource() == btnCalculate)
    			{
    				String strText = txtDisplay.getText();
    				try 
    				{
    					int equation = Integer.parseInt(strText);
    					txtDisplay.setText("" + equation);
    				}
    				catch (ArithmeticException aee)
    				{
    					aee.printStackTrace();
    		 	 }
    			
    			}
    			
    			/*  start the process of finding which operator was 
    			 *  chosen, and the process the equation in a new 
    			 *  method
    			 */
    			 
    			 if (ae.getSource() == btnNums[3])
    			 {
    				 processDivide();
    			 }
    			 else if (ae.getSource() == btnNums[7])
    			 {
    				 processMultiply();
    			 }
    			 else if (ae.getSource() == btnNums[11])
    			 {
    				 processAdd();
    			 }
    			 else if (ae.getSource() == btnNums[13])
    			 {
    				processPosOrNeg();
    			 }
    			 else if (ae.getSource() == btnNums[15])
    			 {
    				 processSubtract();
    			 }
    			 else
    			 {
    			 }
    
    		// and finally process the calculation
    		if (ae.getSource() == btnCalculate)
    		{
    			processCalc();
    		}
    		else
    		{
    		}
    	}
    	
    	public void processDivide()
    	{
    		whichOperator = STR_DIVIDE;
    		strOperand1 = txtDisplay.getText();
    		int x = strOperand1.length();
    		String s = strOperand1.substring(0, x - 1);
    		dd = Double.parseDouble(s);
    		txtDisplay.setText(null);
    	}
    	public void processMultiply()
    	{
    		whichOperator = STR_MULTIPLY;
    		strOperand1 = txtDisplay.getText();
    		int x = strOperand1.length();
    		String s = strOperand1.substring(0, x - 1);
    		dd = Double.parseDouble(s);
    		txtDisplay.setText(null);
    	}
    	public void processAdd()
    	{
    		whichOperator = STR_ADD;
    		strOperand1 = txtDisplay.getText();
    		int x = strOperand1.length();
    		System.out.println("variable x = " + x);
    		String s = strOperand1.substring(0, x - 1);
    		System.out.println("variable s = " + s);
    		dd = Double.parseDouble(s);
    		System.out.println("variable d = " + dd);
    		txtDisplay.setText(null);
    	}
    	public void processPosOrNeg()
    	{
    	}
    	public void processSubtract()
    	{
    		whichOperator = STR_SUBTRACT;
    		strOperand1 = txtDisplay.getText();
    		int x = strOperand1.length();
    		String s = strOperand1.substring(0, x - 1);
    		dd = Double.parseDouble(s);
    		txtDisplay.setText(null);
    	}
    
    	public void processCalc()
    	{
    		strOperand2 = txtDisplay.getText();
    		int x = strOperand2.length();
    		String s = strOperand2.substring(0, x);
    		double d = Double.parseDouble(s);
    		
    		if (whichOperator == STR_SUBTRACT)
    		{
    			double a = dd - d;
    			txtDisplay.setText(dd + "-" + d + " = " + a);
    		}
    		else if (whichOperator == STR_ADD)
    		{
    			double a = dd + d;
    			txtDisplay.setText(dd + "+" + d + " = " + a);
    		}
    		else if (whichOperator == STR_MULTIPLY)
    		{
    				double a = dd * d;
    			txtDisplay.setText(dd + "*" + d + " = " + a);
    		}
    		else if (whichOperator == STR_DIVIDE)
    		{
    				double a = dd / d;
    			txtDisplay.setText(dd + "/" + d + " = " + a);
    		}
    		else 
    		{
    		}
    	
    	}
    	
    	public static void main(String[] args)
    	{
    		Calculator calc = new Calculator();
    	}
    }

  7. #7
    Join Date
    Jan 2005
    Posts
    8
    ooops wrong code..I'll have to take a look at it later, I gotta go.!

  8. #8
    Join Date
    Jan 2005
    Posts
    2
    Here is a class I wrote this weekend for evaluating Math expressions.

    Code:
    import java.util.Vector;
    
    class ExpTree{
    		
    	//used for precedence rules
    	private final static int IS_OPPAR=7;	//open parenthesis
    	private final static int IS_CLPAR=6;	//close parenthesis
    	private final static int IS_PLUS=5;		//addition operator
    	private final static int IS_MINUS=5;	//subtraction operator
    	private final static int IS_MULTI=4;	//multiplication operator
    	private final static int IS_DIV=4;		//division operator
    	private final static int IS_POWER=3;	//power operator
    	
    	
    	//for error handling - not used at the moment
    	//private boolean errorOccured=false;
    	//private String errorMsg;
    	
    	private Vector ops = new Vector(10,2);		//vector where operators are stored to
    	private Vector postfix = new Vector(10,3);	//vector which stores the postfix notation(RPN)
    	
    	//used to find the first occuring operator
    	private static int nextOperatorPos(String subExpr){
    		for(int i=0;i<subExpr.length();i++){
    			if(getOperator(subExpr.substring(i,i+1))>0){
    				return i;
    			}
    		}
    		return -1;
    	}
    	
    	//used to find out which operator it is and for precedence rules
    	private static int getOperator(String chr){
    		int ret=-1;
    		switch(chr.charAt(0)){
    			case '+': ret=IS_PLUS;break;
    			case '-': ret=IS_MINUS;break;
    			case '*': ret=IS_MULTI;break;
    			case '/': ret=IS_DIV;break;
    			case '^': ret=IS_POWER;break;
    			case '(': ret=IS_OPPAR;break;
    			case ')': ret=IS_CLPAR;break;
    			default : ret=-1; 
    		}
    		return ret;
    	}
    	
    	//the method which converts infix to postfix
    	private void doPostfix(boolean expEnd){
    		if(!expEnd){
    			if(ops.size()>1){
    				int actOp=getOperator((String)ops.elementAt(ops.size()-1));
    				if((actOp!=IS_OPPAR)&&(actOp!=IS_CLPAR)){
    					while((ops.size()>1)&&(actOp>=getOperator((String)ops.elementAt(ops.size()-2)))){
    						postfix.add((String)ops.elementAt(ops.size()-2));
    						ops.remove(ops.size()-2);
    					}
    				}else if(actOp==IS_CLPAR){
    					ops.remove(ops.size()-1);
    					while((ops.size()>0)&&(getOperator((String)ops.elementAt(ops.size()-1)))!=IS_OPPAR){
    						postfix.add((String)ops.elementAt(ops.size()-1));
    						ops.remove(ops.size()-1);
    					}
    					if(getOperator((String)ops.elementAt(ops.size()-1))==IS_OPPAR){
    						ops.remove(ops.size()-1);
    					}
    				}	
    			}
    		}else{
    			for(int i=ops.size()-1;i>=0;i--){
    				postfix.add((String)ops.elementAt(i));
    			}
    		}
    	}
    	
    	public double result(double xval){
    		String op;
    		double[] results=new double[postfix.size()];
    		int pos=0;
    		for(int i=0;i<postfix.size();i++){
    			op=(String)postfix.elementAt(i);
    			if(getOperator(op)>-1){
    				switch(op.charAt(0)){
    					case '+': 	results[pos-2]=results[pos-2]+results[pos-1];
    								;break;
    					case '-': 	results[pos-2]=results[pos-2]-results[pos-1];
    								;break;
    					case '*': 	results[pos-2]=results[pos-2]*results[pos-1];
    								;break;
    					case '/': 	results[pos-2]=results[pos-2]/results[pos-1];
    								;break;
    					case '^': 	results[pos-2]=Math.pow(results[pos-2],results[pos-1]);
    								;break;
    				}
    				results[pos-1]=0d;
    				pos--;
    			}else{
    				if((op.equals("x"))||(op.equals("X"))){
    					results[pos]=xval;
    				}else{
    					results[pos]=Double.valueOf(op).doubleValue();
    				}
    				pos++;				
    			}
    		}
    		return results[pos-1];	
    	}
    	
    	//evaluation of the expression (parsing)
    	public void evalExp(String expr){
    		ops.clear();
    		postfix.clear();
    		int nextOpPos;
    		while(expr.length()>0){
    			nextOpPos=nextOperatorPos(expr);
    			if(nextOpPos>0){
    				postfix.add(expr.substring(0,nextOpPos));
    				expr=expr.substring(nextOpPos);
    			}else if(nextOpPos==0){
    				ops.add(expr.substring(nextOpPos,nextOpPos+1));
    				expr=expr.substring(nextOpPos+1);
    				doPostfix(false);
    			}else{
    				postfix.add(expr.substring(0));
    				expr="";
    				doPostfix(false);
    			}
    		}
    		doPostfix(true);
    	}	
    }
    You can use it this way:

    Code:
       //initialize a new expression tree
       ExpTree myExpression=new ExpTree();
      //evaluating the expression
      myExpression.evalExp("(1/30)*x^5-(1/2)*x^3");
      // process the expression
      double myresult = myExpression.result(2);
    - the evalExp method requires the math expression as a String , in your case the String of the Textfield
    - the result method requires a value for the variable x, if there is no variable in the expression use 0 or any other value. It returns a double value

  9. #9
    Join Date
    Jan 2005
    Posts
    8
    Wow! That is extremely helpful..When I look this code over, and figure it out, I'll post the code with the finished calculator..Dude, I really appreciate this!

  10. #10
    Join Date
    Nov 2004
    Location
    Norway
    Posts
    1,560
    I'm trying to embed ExpTree in my version of the calculator, but currently it bugs out on the expression:
    1/2, not to mention the example expression posted here....

    Here is the method that bugs out w. ArrayIndexOutOfBoundsException

    Code:
      private String getValueString(String expression) throws CalculatorException2 {
        expTree.evalExp(expression);
        // this one fails, I have tried argument values  1->3
        return Double.toString(expTree.result(1));
      }
    I fail to see what I'm doing wrong here
    eschew obfuscation

  11. #11
    Join Date
    Nov 2004
    Location
    Norway
    Posts
    1,560
    I've done i minor hack (I think), so ExpTree works w.
    expressions w. no variables, like in the calculator.

    In the method result(double xVal) I changed the
    last line:

    Code:
    //return results[pos-1];	
    return results[0];
    And currently I'm unable to recreate the exception

    Any comments Grone ?
    eschew obfuscation

  12. #12
    Join Date
    Jan 2005
    Posts
    2

    Thumbs up

    I had a look at my code and I couldn't find the error. I tried it with several expressions, even with 1/2 to find it.

    I think you're right with your correction of the last line,
    the result should be in results[0] not in results[pos-1]
    (I don't know why i wrote pos-1 )

  13. #13
    Join Date
    Nov 2004
    Location
    Norway
    Posts
    1,560
    Rats ! I got carried away again...

    Here is my contribution to the calculator, I've embedded
    the ExpTree class to. That class needs some work but
    it will have to do for now.

    Its not at all complete, the memory functions needs
    some more code, but it calculates ...
    Attached Files Attached Files
    eschew obfuscation

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center
 
 
FAQ
Latest Articles
Java
.NET
XML
Database
Enterprise
Questions? Contact us.
C++
Web Development
Wireless
Latest Tips
Open Source


   Development Centers

   -- Android Development Center
   -- Cloud Development Project Center
   -- HTML5 Development Center
   -- Windows Mobile Development Center