How to debug my unconventional Java calculator? - java

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);
}
}
}

Related

Can anyone solve the errors in calculate the arithmetic expressions with stacks?

I wrote a code that reads any arithmetic expression in form of a string and returns the result by printing it.
All of this is done with regard to the order of operation (PEMDAS).
As an example the input, "2+7*5+3" should return 40
But the problem is that the program doesn't return the correct result and I don't know what seems to be the problem.
The Code:
public class LL {
public static int calc(String op, int n1,int n2){
if(op.equals("+")){
return n1+n2;
}
else if(op.equals("-")){
return n1-n2;
}
else if(op.equals("/")){
return n1/n2;
}
else{
return n1*n2;
}
}
public static boolean check(String oldop, String newop){
if(oldop==null||oldop.equals("=")){
return true;
}
else if(oldop.equals("+")||oldop.equals("-")){
if(newop.equals("+")||newop.equals("-")||newop.equals("/")||newop.equals("*")){
return true;
}
else{
return false;
}
}
else{
if(newop.equals("/")||newop.equals("*")){
return true;
}
else{
return false;
}
}
}
public static void main(String[] args) {
int ch=0;
LinkedList<String> op = new LinkedList<String>();
LinkedList<String> nums = new LinkedList<String>();
Scanner sc = new Scanner(System.in);
String exp = sc.nextLine();
String[] exparr = exp.split(" ");
for(int i = 0 ; i<exparr.length-1;i+=2){
nums.push(exparr[i]);
String oldop = op.pop();
if(check(oldop,exparr[i+1])){
if(oldop!=null)
op.push(oldop);
op.push(exparr[i+1]);
}
else{
String n2=nums.pop();
String n1=nums.pop();
int nn2=Integer.parseInt(n2);
int nn1=Integer.parseInt(n1);
int res = calc(oldop,nn1,nn2);
nums.push(Integer.toString(res));
op.push(exparr[i+1]);
}
}
nums.push(exparr[exparr.length-1]);
String opp = op.pop();
while(opp!=null){
String n2=nums.pop();
String n1=nums.pop();
int nn2=Integer.parseInt(n2);
int nn1=Integer.parseInt(n1);
int res = calc(opp,nn1,nn2);
nums.push(Integer.toString(res));
opp = op.pop();
}
System.out.println(nums.pop());
}
}
Your check method is wrong. You must return true if the old operation is + or - and the new operation is * or / otherwise return false.
public static boolean check(String oldop, String newop){
if(oldop == null || oldop.equals("=")){
return true;
}
return (oldop.equals("+") || oldop.equals("-")) && (newop.equals("/") || newop.equals("*"));
}
Another point is, don't use pop method of LinkedList, this method throws an exception if the list is empty, use poll method that return null if the list is empty.
The other code is correct.

infix arithmetic expression definition

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 :)

Check repetition of fractions of external file

I'm creating a program that has a requirement of three classes. The program reads an external text file filled with fractions, and is to return how many times each fraction is repeated. 4/2 has to be reduced to 2/1 and is +1 for the 2/1 count. I believe I am almost done, but I cannot figure out what I need to put into my compareAndIncrement() method in my FractionCounter class. It is suppose to be used to see if the newFraction passed into the function is the same as the Fraction being stored, and if so increments the counter by one and returns true (otherwise, returns false). Below are the codes for my classes.
FractionCounter
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class FractionCounter {
private Fraction theFraction;
private int counter = 0;
public FractionCounter(Fraction theFraction ){
}
public boolean compareAndIncrement(Fraction newFraction){
return false;
}
public String toString(){
return "";
}
public static void main(String[] args){
ObjectList num = new ObjectList();
ObjectList den = new ObjectList();
Scanner fractionFile = null;
try{
fractionFile = new Scanner(new FileInputStream("fractions.txt"));
}
catch (FileNotFoundException e){
System.out.println("File not found.");
System.exit(0);
}
while (fractionFile.hasNextLine()){
String[] part = (fractionFile.nextLine().split("/"));
num.add(Integer.parseInt(part[0]));
den.add(Integer.parseInt(part[1]));
}
}
}
Fraction
public class Fraction {
private int numerator;
private int denominator;
public Fraction() {
}
public Fraction(int num, int den) {
setNumerator(num);
setDenominator(den);
}
public void setNumerator(int num) { //sets numerator
numerator = num;
}
public int getNumerator() { //gets numerator
return numerator;
}
public void setDenominator(int den) { //sets denominator
if(den == 0) {
System.out.println("Error: Denominator = 0");
System.exit(0);
} else {
denominator = den;
}
}
public int getDenominator() { //gets denominator
return denominator;
}
public boolean equals(Fraction that) {
return ((double)this.numerator/this.denominator) == ((double)that.numerator/that.denominator);
}
}
ObjectList
public class ObjectList {
private int[] fraction = new int[100];
private int numElements = 0;
public void add(int n){
fraction[numElements] = n;
numElements++;
}
public String toString(){
String retVal = "";
for (int i = 0; i < numElements; i++){
retVal += fraction[i] + ",";
}
return retVal;
}
public int indexOf(int[] input, int target) {
//returns the index of the inputed value
if(contains(input,target) == true){
for(int i = 0;i <= target;i++) {
if(input[i] == target) {
return i;
}
}
}
return -1;
}
public boolean contains(int[] input, int target) {
//is the target in the inputed array?
for(int i=0;i<input.length; i++) {
if(input[i] == target) {
return true;
}
}
return false;
}
}
Any hints or tips for what I need to do to my method would be much appreciated. I can't figure out a way to do it without using numElements and fraction variables from my ObjectList class. Thank you
I would make a Map to make the counter :
private static final Map<Fraction, Integer> counter = new HashMap<Fraction, Integer>();
and for each Fraction element read for the file I would do :
if(counter.containsKey(fraction)){
Integer count = counter.get(fraction);
count++;
counter.put(fraction, count);
} else {
counter.put(fraction, 1);
}
Moreover, I would make a static parse fonction in the Fraction class which return a Fraction instance from the line you just read. And a toString function to print it easely.

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.

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