infix arithmetic expression definition - java

How is the grammar for infix arithmetic expressions, defined? I have code of a infix 'calculator', but I need to know, in words or some type of examples how to define the grammar.
the code:
import java.util.Stack;
import java.util.StringTokenizer;
public class Infix
{
public double infix(String expression)
{
expression=expression.replaceAll("[\t\n ]", "")+"=";
String operator="*/+-=";
StringTokenizer tokenizer=new StringTokenizer(expression, operator, true);
Stack operatorStack=new Stack();
Stack valueStack=new Stack();
while(tokenizer.hasMoreTokens())
{
String token=tokenizer.nextToken();
if(operator.indexOf(token)<0)
valueStack.push(token);
else
operatorStack.push(token);
resolve(valueStack, operatorStack);
}
String lastOne=(String)valueStack.pop();
return Double.parseDouble(lastOne);
}
public int getPriority(String op)
{
if(op.equals("*") || op.equals("/"))
return 1;
else if(op.equals("+") || op.equals("-"))
return 2;
else if(op.equals("="))
return 3;
else
return Integer.MIN_VALUE;
}
public void resolve(Stack values, Stack operators)
{
while(operators.size()>=2)
{
String first=(String)operators.pop();
String second=(String)operators.pop();
if(getPriority(first)<getPriority(second))
{
operators.push(second);
operators.push(first);
return;
}
else
{
String firstValue=(String)values.pop();
String secondValue=(String)values.pop();
values.push(getResults(secondValue, second, firstValue));
operators.push(first);
}
}
}
public String getResults(String operand1, String operator, String operand2)
{
System.out.println("Performing "+
operand1+operator+operand2);
double op1=Double.parseDouble(operand1);
double op2=Double.parseDouble(operand2);
if(operator.equals("*"))
return ""+(op1*op2);
else if(operator.equals("/"))
return ""+(op1/op2);
else if(operator.equals("+"))
return ""+(op1+op2);
else if(operator.equals("-"))
return ""+(op1-op2);
else
return null;
}
public static void main(String[] args)
{
Infix fix=new Infix();
String expression="5-3*2*1/2+2";
System.out.println(expression+"="+fix.infix(expression));
}
}
Also, if u don't mind, is there a better, easier to understand way of coding this? (this is not as important as the grammar definition) I hope you understand my request :)

Related

Validating input string with java

First off, I will admit that this is an assignment of mine. however, I am at my wits end. I tried need to validate that the user input a proper expression (ie: "7 + 5;") and I managed to do it with split methods but I was told that I can't do that. I'm sure there is a simple solution to the problem but I am not seeing it.
The code is rather lengthy so I won't post it but if I will if needed.
Thanks!
Edit to answer questions: I am writing in jGrasp, so they can do whatever is on the keyboard. I was told to "Find a creative way to use substrings" which I don't know what that means. The expression needs to be Number Space operand Space number semicolon
here is what I have for the validation... I am using arrays for each character in the expression
public static boolean validFormat(String expr)
{
String tokens[] = expr.substring()
if (tokens.length == 3)
{
if (tokens[0].equals(""))
{
return false;
}
if (tokens[1].equals(""))
{
return false;
}
if (tokens[2].length < 2)
{
return false;
}
else
{
if (tokens[2].endwith(";"));
{
return false;
}
else
{
return true;
}
}
}
return false;
}
I get an error with calling the substring as well as an "else without if" error
First, you should limits the input to 6 characters using an if statement. Then use the CharAt() method to return each character to check the condition.
I was told to "Find a creative way to use substrings".
As told, try using String.substring() for the same.
public class Demo {
public static void main (String[] args) {
String exp = "7 + 5;";
System.out.printf("%s\t%b%n", exp, validate(exp));
exp = "4 + d;";
System.out.printf("%s\t%b%n", exp, validate(exp));
}
public static boolean validate(String exp) {
String n1 = exp.substring(0,1);//operand
String n2 = exp.substring(4,5);//operand
String co = exp.substring(5);//semicolon
String s1 = exp.substring(1,2);//space
String s2 = exp.substring(3,4);//space
String op = exp.substring(2,3);//operator
return num(n1) && num(n2) && semi(co) && space(s1) && space(s2) && opt(op);
}
public static boolean num(String n) {
return "0123456789".contains(n);
}
public static boolean semi(String s) {
return ";".equals(s);
}
public static boolean space(String s) {
return " ".equals(s);
}
public static boolean opt(String s) {
return "-+*%/^".contains(s);
}
}
This solution uses RegExp:
public class Demo {
public static void main (String[] args) {
String exp = "7 + 5;";
System.out.printf("%s\t%b%n", exp, validate(exp));
exp = "4 + d;";
System.out.printf("%s\t%b%n", exp, validate(exp));
}
public static boolean validate(String exp) {
return exp.matches("\\d\\s(\\+|\\-|\\*|\\/|\\^|\\%)\\s\\d\\;");
}
}

How to debug my unconventional Java calculator?

I just finished programming a calculator that performs the four basic arithmetic operations, plus six trigonometric operations, in an interface so minimalistic that it just lets the user enter the expression and displays the result, with no need for separate input of operands and operator.
I think it saves time for the user and would look more finished, for lack of a better word, if it would only work.
import java.util.*;
public class Calculator
{
public static String getOperator(String expression)
{
int counter=0;
for (int i=0; i<3; i++)
{
if (Character.isLetter(expression.charAt(i)))
counter++;
}
if (counter==3)
return expression.substring(0, 3);
else
{
for (int j=0; j<expression.length(); j++)
{
if (Character.isDigit(expression.charAt(j))==false)
{
if (expression.charAt(j)!='.')
return Character.toString(expression.charAt(j));
}
}
}
return "false";
}
public static double getFirstOperand(String operator, String expression)
{
return Double.parseDouble(expression.substring(expression.indexOf(operator)+1));
}
public static String getOperatorType(String expression)
{
int counter=0;
for (int i=0; i<3; i++)
{
if (Character.isLetter(expression.charAt(i)))
counter++;
}
if (counter==3)
return "Trigonometrical";
else
return "Arithemtic";
}
public static double getResult(String operator, double operand)
{
if (operator.equals("sin"))
return Math.sin(operand);
if (operator.equals("cos"))
return Math.cos(operand);
if (operator.equals("tan"))
return Math.tan(operand);
if (operator.equals("cot"))
return 1/Math.tan(operand);
if (operator.equals("cosec"))
return 1/Math.sin(operand);
else
return 1/Math.cos(operand);
}
public static double getSecondOperand(String expression)
{
return Double.parseDouble(expression.substring(0, expression.indexOf(expression)));
}
public static double getResult(String operator, double operand1, double operand2)
{
if (operator.equals("*"))
return operand1*operand2;
if (operator.equals("+"))
return operand1+operand2;
if (operator.equals("/"))
return operand2/operand1;
else
return operand2-operand1;
}
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
String command="", operator="", operatorType="";
double operand1=0.0, operand2=0.0, result=0.0;
while (command.equals("EXIT")=false)
{
System.out.println("Enter command: ");
command = sc.next();
operator = getOperator(command);
operand1 = getFirstOperand(operator, command);
operatorType = getOperatorType(command);
if (operatorType.equals("Trigonometrical"))
result=getResult(operator, operand1);
if (operatorType.equals("Arithmetic"))
{
operand2 = getSecondOperand(command);
result=getResult(operator, operand1, operand2);
}
System.out.println("Result="+result);
}
}
}
Somehow, whatever I input, the result is always 0.0.
Enter command:
45*2
Result=0.0
Enter command:
2+2
Result=0.0
I don't understand where the problem is. I've searched through the code tens of times, but I just don't see it.
UPDATE: Thanks for all your help, guys. The calculator finally works as it should. In fact, nearly all the problems were caused by a single lethal error in getSecondOperand. I've fixed the code now and the repaired code is given below.
You have a typo in "Arithmetic" in getOperatorType():
public static String getOperatorType(String expression)
{
int counter=0;
for (int i=0; i<3; i++)
{
if (Character.isLetter(expression.charAt(i)))
counter++;
}
if (counter==3)
return "Trigonometrical";
else
return "Arithemtic";
}
This is why you should avoid Strings for such cases, and favor Enums instead.
Furthermore, you're comparing Strings using ==, which won't work. Use equals() instead. Or, use Enums instead.
Here's the solution:
import java.util.*;
public class Calculator
{
public static String getOperator(String expression)
{
int counter=0;
for (int i=0; i<3; i++)
{
if (Character.isLetter(expression.charAt(i)))
counter++;
}
if (counter==3)
return expression.substring(0, 3);
else
{
for (int j=0; j<expression.length(); j++)
{
if (Character.isDigit(expression.charAt(j))==false)
return Character.toString(expression.charAt(j));
}
}
return "false";
}
public static double getFirstOperand(String operator, String expression)
{
return Double.parseDouble(expression.substring(expression.lastIndexOf(operator)+1));
}
public static String getOperatorType(String expression)
{
int counter=0;
for (int i=0; i<3; i++)
{
if (Character.isLetter(expression.charAt(i)))
counter++;
}
if (counter==3)
return "Trigonometrical";
else
return "Arithmetic";
}
public static double getResult(String operator, double operand)
{
if (operator.equals("sin"))
return Math.sin(operand);
if (operator.equals("cos"))
return Math.cos(operand);
if (operator.equals("tan"))
return Math.tan(operand);
if (operator.equals("cot"))
return 1/Math.tan(operand);
if (operator.equals("cosec"))
return 1/Math.sin(operand);
else
return 1/Math.cos(operand);
}
public static double getSecondOperand(String expression, String operator)
{
return Double.parseDouble(expression.substring(0, expression.indexOf(operator)));
}
public static double getResult(String operator, double operand1, double operand2)
{
if (operator.equals("*"))
return operand1*operand2;
if (operator.equals("+"))
return operand1+operand2;
if (operator.equals("/"))
return operand2/operand1;
else
return operand2-operand1;
}
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
String command="", operator="", operatorType="";
double operand1=0.0, operand2=0.0, result=0.0;
char exitNow='0';
while (exitNow=='0'||exitNow=='N')
{
System.out.println("Enter command: ");
command = sc.next();
operator = getOperator(command);
operand1 = getFirstOperand(operator, command);
operatorType = getOperatorType(command);
if (operatorType.equals("Trigonometrical"))
result=getResult(operator, operand1);
if (operatorType.equals("Arithmetic"))
{
operand2 = getSecondOperand(command, operator);
result=getResult(operator, operand1, operand2);
}
System.out.println("Result="+result+"\nExit now(1/0)(Y/N)");
exitNow=sc.next().charAt(0);
}
}
}

Math Expression Parser

I found the code of Math Expression Parser from Dreamincode Forum.
My question is, on that code I think everything is going all right, but when I had a testcase '(2(3+5)' , that was valid, whereas this test case is completely wrong
but if I give the test case '(3+5)2)' it was detect as non valid input.
Anyone knows why this is happening?
//enum for Operator "objects"
import java.util.*;
public enum Operator {
ADD("+", 1)
{
double doCalc(double d1, double d2) {
return d1+d2;
}
},
SUBTRACT("-",1)
{
double doCalc(double d1, double d2) {
return d1-d2;
}
},
MULTIPLY("*", 2)
{
double doCalc(double d1, double d2) {
return d1*d2;
}
},
DIVIDE("/",2)
{
double doCalc(double d1, double d2) {
return d1/d2;
}
},
STARTBRACE("(", 0)
{
double doCalc(double d1, double d2) {
return 0;
}
},
ENDBRACE(")",0)
{
double doCalc(double d1, double d2) {
return 0;
}
},
EXP("^", 3)
{
double doCalc(double d1, double d2) {
return Math.pow(d1,d2);
}
};
private String operator;
private int precedence;
private Operator(String operator, int precedence) {
this.operator = operator;
this.precedence = precedence;
}
public int getPrecedenceLevel() {
return precedence;
}
public String getSymbol() {
return operator;
}
public static boolean isOperator(String s) {
for(Operator op : Operator.values()) { //iterate through enum values
if (op.getSymbol().equals(s))
return true;
}
return false;
}
public static Operator getOperator(String s)
throws InvalidOperatorException {
for(Operator op : Operator.values()) { //iterate through enum values
if (op.getSymbol().equals(s))
return op;
}
throw new InvalidOperatorException(s + " Is not a valid operator!");
}
public boolean isStartBrace() {
return (operator.equals("("));
}
//overriding calculation provided by each enum part
abstract double doCalc(double d1, double d2);
}
//error to be thrown/caught in ProjectOne.java
class InvalidOperatorException extends Exception {
public InvalidOperatorException() {
}
public InvalidOperatorException(String s) {
super(s);
}
}
//reading in a string at doing the parsing/arithmetic
public static void main (String[] args) {
String input = "";
//get input
System.out.print("Enter an infix exp<b></b>ression: ");
BufferedReader in = new BufferedReader(
new InputStreamReader(System.in));
try {
input = in.readLine();
}
catch (IOException e)
{
System.out.println("Error getting input!");
}
doCalculate(input);
}
// Input: user entered string
// Output: Display of answer
public static void doCalculate(String equation) {
//our stacks for storage/temp variables
Stack<Operator> operatorStack;
Stack<Double> operandStack;
double valOne, valTwo, newVal;
Operator temp;
//initalize
StringTokenizer tokenizer = new StringTokenizer(equation, " +-*/()^", true);
String token = "";
operandStack = new Stack();
operatorStack = new Stack();
try {
while(tokenizer.hasMoreTokens()){ //run through the string
token = tokenizer.nextToken();
if (token.equals(" ")) { //handles spaces, goes back up top
continue;
}
else if (!Operator.isOperator(token)){ //number check
operandStack.push(Double.parseDouble(token));
}
else if (token.equals("(")) {
operatorStack.push(Operator.getOperator(token));
}
else if (token.equals(")")) { //process until matching paraentheses is found
while (!((temp = operatorStack.pop()).isStartBrace())) {
valTwo = operandStack.pop();
valOne = operandStack.pop();
newVal = temp.doCalc(valOne, valTwo);
operandStack.push(newVal);
}
}
else { //other operators
while (true) { //infinite loop, check for stack empty/top of stack '('/op precedence
if ((operatorStack.empty()) || (operatorStack.peek().isStartBrace()) ||
(operatorStack.peek().getPrecedenceLevel() < Operator.getOperator(token).getPrecedenceLevel())) {
operatorStack.push(Operator.getOperator(token));
break; //exit inner loop
}
temp = operatorStack.pop();
valTwo = operandStack.pop();
valOne = operandStack.pop();
//calculate and push
newVal = temp.doCalc(valOne, valTwo);
operandStack.push(newVal);
}
}
}
}
catch (InvalidOperatorException e) {
System.out.println("Invalid operator found!");
}
//calculate any remaining items (ex. equations with no outer paraentheses)
while(!operatorStack.isEmpty()) {
temp = operatorStack.pop();
valTwo = operandStack.pop();
valOne = operandStack.pop();
newVal = temp.doCalc(valOne, valTwo);
operandStack.push(newVal);
}
//print final answer
System.out.println("Answer is: " + operandStack.pop());
}
This calculator does not work with implicit multiplication. you can use:
2((2+2)+1)
And see that it gives the wrong answer as opposed to:
2*((2+2)+1)
The false-positive expression you've used does not pass with explicit multiplication.
A quick for-the-lazy fix to add implicit multiplication would be something of that sort:
public static void doCalculate(String equation) {
// make it explicit:
System.out.println("Got:" + equation);
Pattern pattern = Pattern.compile("([0-9]+|[a-z\\)])(?=[0-9]+|[a-z\\(])");
Matcher m = pattern.matcher(equation);
System.out.println("Made it: "+ (equation = m.replaceAll("$1*")));
//our stacks for storage/temp variables
Stack<Operator> operatorStack;
Stack<Double> operandStack;
double valOne, valTwo, newVal;
Operator temp;
This is an attempt to capture implicit multiplication using regex and make it explicit.
It fixes all cases we've come up with.

Need help in implementing Java Algorithm on Postfix Evaluation

I've tried writing this code from scratch, coding, and running it but it just doesn't seem to work. This was assigned as lab work in class. The requirements are:
Implementing a postfix evaluation with the use of a stack and stack operations (user-defined).
I think the algorithm of my program is right, but it always gives me the wrong answer.
Here is my code.
public class StackApplication {
public static class Stack<T> {
private int top = 0;
private final static int stackMax=100;
// highest index of stk array
private Object[] stk = new Object[stackMax+1];
//Elements must be cast back.
public Stack() { // constructor
}
public boolean isEmpty(){
if (top==0) return true;
else return false;
}
public void push(T el) {
if(top==stackMax)
System.out.println("Stack push overflow error");
else top=top+1;
stk[top]=el;
}
public T pop(){
if(isEmpty()){
System.out.println("Stack push underflow error");
return null;
}
else top=top-1;
return(T)stk[top+1];
}
public T top(){
if(isEmpty()){
//System.out.println("Stack empty");
return null;
}
else return (T)stk[top];
}
}
public static boolean isOperator(char c){
return(c=='+' || c=='-' || c=='/' || c=='*' || c=='^');
}
public static double evaluate(double x, char o, double y) {
double result=0;
switch(o) {
case '+' : result=x+y; break;
case '-' : result=x-y; break;
case '*' : result=x*y; break;
case '/' : result=x/y; break;
case '^' : result=Math.pow(x, y); break;
default : break;
}
return result;
}
public static void main(String[] args) {
Scanner console=new Scanner(System.in);
Stack<Double> s=new Stack<Double>();
System.out.println("Input Postfix form to evaluate:");
String inp=console.nextLine();
char[] chararray=inp.toCharArray();
double b,a;
for(int i=0; i<chararray.length; i++) {
if(!isOperator(chararray[i]))
s.push((double)chararray[i]);
else {
b=s.pop();
a=s.pop();
double c=evaluate(a, chararray[i], b);
s.push(c);
}
}
System.out.println(" " +s.pop());
}
}
Sample Output:
Input Postfix form to evaluate:
23+ (Input)
101.0 (Output)
5.0 (Expected output)
The problem is here: s.push((double)chararray[i]);. You can't convert char to double this way. You are now taking the ascii code of 2 and 3.
50(ascii code of 2) + 51(ascii code of 3) = 101
Do it like this: s.push((double)(chararray[i] - '0'));
Your are doing the addition of the ASCII codes for 2 and 3, not of 2 and 3.
The code for 2 is 50 and for 3 is 51, so your out is 101, which is correct in this case.
When you push, push chararray[i]-'0'. This will solve your problem.

Making a simple calculator: cannot exit loop or give answer

I need to make a simple calculator. I am having trouble with entering any amount of operators and operands, then outputting the answer when the equals button has been entered.
So far, if I just press one number and a digit it exits but does not give me an answer. If I do more than one operator and operand then = it does not exit the loop.
For example it should be like:
5
+
5
+
5
=
15
Here is my code, Calculator:
public interface Calculator {
public void setOperator(char operator); // eg +-*/=
public void setOperand (double operand); // eg 123.456
public double getResult();
}
SimpleCalculator:
import java.io.*;
public class SimpleCalculator implements Calculator {
char operator;
double operand;
double result;
double answer;
public void setOperator(char operator){
this.operator = operator;
}
public char getOperator(){
return operator;
}
public void setOperand(double operand){
this.operand = operand;
}
public double getOperand(){
return operand;
}
public double getResult(){
if (getOperator() == '+'){
result = (getOperand() + getOperand());
}
if (getOperator() == '-'){
result = (getOperand() - getOperand());
}
if (getOperator() == '*'){
result = (getOperand() * getOperand());
}
if (getOperator() == '/')
{
result = (getOperand() / getOperand());
}
if (getOperator() == '=')
result = answer;
}
return result;
}
public boolean getanswer(String value)
{
boolean isnum = false;
try {
setOperand(Double.parseDouble(value));
operand = (Double.parseDouble(value));
getResult();
isnum = true;
}
catch(Exception e)
{
try {
setOperator(value.charAt(0));
operator = (value.charAt(0));
isnum = false;
}
catch(Exception e2)
{
{
System.out.println("Enter a number");
}
}
return isnum;
}
}
SimpleTest:
import java.io.*;
public class SimpleTest{
static String value;
static double operand;
static char operator;
static boolean isnum;
public static void main(String[] argv){
SimpleCalculator calculator = new SimpleCalculator();
value = UserInput.readString();
while (!(value.equals("=")))
{
isnum = calculator.getanswer(value);
if (!(isnum == true))
{
break;
}
}
System.out.println(calculator.getResult());
}
}
Based on the title of your question I found that you might see an issue with your main-loop:
value = UserInput.readString();
while (!(value.equals("="))) {
isnum = calculator.getanswer(value);
if (!(isnum == true)) {
break;
}
}
Since you read the user input outside the loop it will never change and this will either run only once (if isnum is false) or infinitely (if isnum is true) -- getanswer does not has a memory with respect to its result. Thus if you input a number it will loop forever but not doing anything useful.
Please note: this is just a first guess. I didn't check the rest of your program.
You didn't really say what your problem is, but I found one for you:
You are using
result = (getOperand() + getOperand();
(and similar) to calculate your results. But getOperand() always returns the same result (since you can't execute setOperand() between these calls), so you are always adding, subtracting, multiplying and dividing the same number.

Categories