I'm trying to make a recursive program that reads and evaluates fully parenthesized arithmetic expressions. The program was already made, my task is to make the method evaluates recursively. However, I'm having a bit of difficulty doing this. I have gotten much done, but I'm now getting an error - java.lang.NumberFormatException - and I can't seem to figure out why and where it's coming from. Could someone please help me as I have been at this for a week and need some help desperately.
Heres my code:
package q2;
// FILE: EvaluateDemonstration.java
// This program reads a reads and evaluates fully parenthesized arithmetic
// expressions. The purpose is to illustrate a fundamental use of stacks.
import java.util.Scanner;
import java.util.regex.Pattern;
public class RecursiveEvaluateDemonstration
{
public static void main(String[ ] args)
{
Scanner stdin = new Scanner(System.in);
String expression;
double answer;
System.out.println("Please type an arithmetic expression made from");
System.out.println("unsigned numbers and the operations + - * /.");
System.out.println("The expression must be fully parenthesized.");
do
{
System.out.print("Your expression: ");
expression = stdin.nextLine( );
try
{
answer = evaluate(expression,0,0,0);
System.out.println("The value is " + answer);
}
catch (Exception e)
{
System.out.println("Error." + e.toString( ) + " Help");
}
}
while (query(stdin, "Another string?"));
System.out.println("All numbers are interesting.");
}
public static boolean query(Scanner input, String prompt)
{
String answer;
System.out.print(prompt + " [Y or N]: ");
answer = input.nextLine( ).toUpperCase( );
while (!answer.startsWith("Y") && !answer.startsWith("N"))
{
System.out.print("Invalid response. Please type Y or N: ");
answer = input.nextLine( ).toUpperCase( );
}
return answer.startsWith("Y");
}
public static double evaluate(String s, int i,int j, int charIndex)
// Precondition: The string is a fully parenthesized arithmetic expression
// formed from non-negative numbers, parentheses, and the four operations
// +, -, *, and /.
// Postcondition: The string has been evaluated and the value returned.
// Exceptions: Can throw an NumberFormatException if the expression contains
// characters other than digits, operations, parentheses and whitespace.
// Can throw IllegalArgumentException if the input line is an
// illegal expression, such as unbalanced parentheses or a division by zero.
{
double[] numbers = new double[3] ;
Character[] operations = new Character[1];
String next = "";
int length = s.length();
char first;
int numIndex = i;
int operatIndex = j;
if (charIndex < length)
{
if (Character.isDigit(s.charAt(charIndex))) //|| s.charAt(charIndex) == '.' )
{
next += s.charAt(charIndex);
}
else
{
first = s.charAt(charIndex);
switch (first)
{
case '+': // Addition
case '-': // Subtraction
case '*': // Multiplication
case '/': // Division
numbers[numIndex]=(new Double(next));
System.out.println(numbers[numIndex]);
operations[operatIndex] = first;
break;
case ')': // Right parenthesis
evaluateStackTops(numbers, operations);
break;
case '(': // Left parenthesis
break;
default : // Illegal character
throw new IllegalArgumentException("Illegal character");
}
}
evaluate(s, ++numIndex, operatIndex+1, charIndex+1);
}
if (numbers.length != 3)
throw new IllegalArgumentException("Illegal input expression");
return numbers[2];
}
public static void evaluateStackTops(double[] numbers, Character[] operations)
// Precondition: The top of the operations stack contains +, -, *, or /, and
// the numbers stack contains at least two numbers.
// Postcondition: The top two numbers have been popped from the numbers stack, and the
// top operation has been popped from the operations stack. The two numbers have been
// combined using the operation (with the second number popped as the left operand).
// The result of the operation has then been pushed back onto the numbers stack.
// Exceptions: Throws an IllegalArgumentException if the stacks are illegal or if the
// operation results in a division by zero.
{
double operand1, operand2;
// Check that the stacks have enough items, and get the two operands.
if ((numbers.length < 2))
throw new IllegalArgumentException("Illegal expression");
operand2 = numbers[1];
operand1 = numbers[0];
// Carry out an action based on the operation on the top of the stack.
switch (operations[0])
{
case '+': numbers[2] = (operand1 + operand2);
break;
case '-': numbers[2] = (operand1 - operand2);
break;
case '*': numbers[2]= (operand1 * operand2);
break;
case '/': // Note: A division by zero results in POSTIVE_INFINITY or
// NEGATIVE_INFINITY.
numbers[2] = (operand1 / operand2);
break;
default : throw new IllegalArgumentException("Illegal operation");
}
}
// These patterns are from Appendix B of Data Structures and Other Objects.
// They may be used in hasNext and findInLine to read certain patterns
// from a Scanner.
public static final Pattern CHARACTER =
Pattern.compile("\\S.*?");
public static final Pattern UNSIGNED_DOUBLE =
Pattern.compile("((\\d+\\.?\\d*)|(\\.\\d+))([Ee][-+]?\\d+)?.*?");
}
Here's the trace:
Exception in thread "main" java.lang.NumberFormatException: empty String
at sun.misc.FloatingDecimal.readJavaFormatString(Unknown Source)
at java.lang.Double.valueOf(Unknown Source)
at java.lang.Double.<init>(Unknown Source)
at q2.RecursiveEvaluateDemonstration.evaluate(RecursiveEvaluateDemonstration.java:94)
at q2.RecursiveEvaluateDemonstration.evaluate(RecursiveEvaluateDemonstration.java:107)
at q2.RecursiveEvaluateDemonstration.evaluate(RecursiveEvaluateDemonstration.java:107)
at q2.RecursiveEvaluateDemonstration.main(RecursiveEvaluateDemonstration.java:29)
You're probably getting the number format exception because you're doing
case '+': // Addition
case '-': // Subtraction
case '*': // Multiplication
case '/': // Division
numbers[numIndex]=(new Double(next));
But at this point, the next could be the empty string "", so it will fail with that.
Add
e.printStackTrace();
to the catch block in the main method and run the program again with same input to receive the stacktrace, then share the stacktrace here.
Related
I'm new to learning java. My current assignment is to have the user enter the values they want with an operator and come out with a result on one line with no spaces.
I figured out most of the code, but I'm having trouble running it without adding the spaces.
For example:
1 + 1 = 2 (This will work)
1+1 (this causes an error)
Here is my code:
import java.util.Scanner;
public class Mod2 {
Scanner sc = new Scanner(System.in);
static int value1;
static int value2;
static int result;
String input = "";
public static void main(String[] args){
Mod2 m = new Mod2();
System.out.println("Beginning Application");
System.out.println("Enter expression like [value][operator][value2] no spaces");
value1 = m.sc.nextInt();
String input = m.sc.next();
value2 = m.sc.nextInt();
switch (input) {
case "+":
result = (value1 + value2);
System.out.println(result);
break;
case "-":
result = (value1 - value2);
System.out.println(result);
break;
case "*":
result = (value1 * value2);
System.out.println(result);
break;
case "/":
result = (value1 / value2);
System.out.println(result);
break;
case "%":
result = (value1 % value2);
System.out.println(result);
break;
}
System.out.println("Ending application");
System.exit(0);
}
}
You can split the input string by the operator then use the first half of that string as value 1 then second half as value 2.
input.split("-"); // you can use a regex expression here to check for the existence of the operator
...
String input = m.sc.next();
String[] operation = input.split("(?<=\\d)(?=\\D)|(?<=\\D)(?=\\d)");
Integer value1 = Integer.parseInt(operation[0]);
Integer value2 = Integer.parseInt(operation[2]);
switch (operation[1]) {
case "+":
result = (value1 + value2);
break;
case "-":
result = (value1 - value2);
break;
case "*":
result = (value1 * value2);
break;
case "/":
result = (value1 / value2);
break;
case "%":
result = (value1 % value2);
break;
}
System.out.println(result);
That should let you input "2+2" and produce 4 as result
For the nextXXX()-methods (except nextLine()) Scanner uses strings up to some delimiter as its tokens. By default, whitespace is used as delimiter. Since e. g. string "100+50" doesn't contain any whitespace, it's a single token. This token is not an int, therefore a call on nextInt() will fail.
What can you do? Either you read the whole line using nextLine(), then you'll have to parse it on your own.
Or, you use different delimiters. E.g.
m.sc.useDelimiter("[^0-9]"); // delimiter is any non-digit.
int value1 = m.sc.nextInt();
m.sc.useDelimiter("[0-9]"); // delimiter is any digit
String operator = m.sc.next();
m.sc.useDelimiter("[^0-9]"); // delimiter is any non-digit.
int value2 = m.sc.nextInt();
The delimiter is a regular expression. You can find more information on those in the documentation for Pattern.
EDIT: note, the used expressions won't work with negative numbers.
I don't know if I understand but the problem occurs when there is space in the right operator?
You can simply remove the operator spaces before entering the switch, like this:
input = input.replaceAll(" ","");
switch (input) {...
I was just trying to code a simple calculator and it works fine...
What I want to do now is include a 'do while' or 'while' loop to repeat a statement till a user enters one of the four basic operator signs. I have achieved it using other methods (if and switch) but I want to simplify it.
Also I faced a lot of problems learning how to parse a character in scanner and JPane methods. I could achieve using various resources on the internet but a simple method that would help me understand the logic more clearly and not just achieve will be highly appreciated...
public class MyCalculator{
public static void main (String [] args){
// Let us code a simple calculator
char OP;
System.out.println("This is a simple calculator that will do basic calculations such as :\nAddition, Multiplication, Substraction and Division.");
// Create a scanner object to Read user Input.
Scanner input = new Scanner(System.in);
System.out.println("Enter Any positive number followed by pressing ENTER.");
int firstNum = input.nextInt();
// Need to Loop the below statement till one of the four (+,-,*,/) operator is entered.
System.out.println("Enter your choice of OPERATOR sign followed by pressing ENTER.");
OP = input.next().charAt(0);
System.out.println("Enter your Second number followed by an ENTER stroke.");
int secNum = input.nextInt();
// Various possible Resolution
int RSum = firstNum+secNum;
int RSubs= firstNum-secNum;
int RPro = firstNum*secNum;
double DPro = firstNum/secNum;
// Conditional statements for Processing
Switch (OP){
case '+': System.out.println("The Resulting sum is "+ RSum);
break;
case '-': System.out.println("The Resulting sum is "+ RSubs);
break;
case '*': System.out.println("The Resulting Product is "+ RPro);
break;
case '/': System.out.println("The Resulting Divisional product is "+ DPro);
break;
default : System.out.println("Try Again");
}
}
}
You can use something like this:
while(scanner.hasNext()) {
//some code
int number = scanner.NextInt();
}
But I would implement a calculator as follow:
int num1 = scanner.NextInt();
String op = scanner.Next();
int num2 = scanner.NextInt();
You can loop through a String as follow and do your checks:
for (char ch : exampleString.toCharArray()){
System.out.println(ch);
}
You can also loop through a String as follow:
for (int i=0; i<examplestring.length(); i++) {
char c = examplestring.charAt(i);
}
You can loop until you get a + or a - as follow:
char operator;
do {
char operator = scanner.next().get(0);
}while(operator != '+' || operator != '-')
You can loop and print error messages as follow:
char operator;
do {
char operator = scanner.next().get(0);
if(!isValidOperator(operator)) {
System.out.println("invalid operator");
}
}while(!isValidOperator(operator))
public boolean isValidOperator(char operator) {
if(operator == '+') {
return true;
} else if (operator == '-') {
return true;
}
return false;
}
I got most of the code out of the text book and every thing seems to be working. For example if I have the postfix 5 2 + it would give me 7, which is correct but if I have 5 2 4 * / 7 - then it throws the illegal input exception. When I got rid of the illegal input exception, it works but doesn't give the right answer.
import java.util.*;
import java.util.regex.Pattern;
//Here is my class and main method
public class postFix {
public static final Pattern UNSIGNED_DOUBLE = Pattern.compile("((\\d+\\.?\\d*)|(\\.\\d+))([Ee][-+]?\\d+)?.*?");
public static final Pattern CHARACTER = Pattern.compile("\\S.*?");
public static Double postfixEvaluate (String expression) {
Stack<Double> numbers = new Stack<Double>( ); //Stack for numbers
Stack<Character> operators = new Stack<Character>( ); //Stack for ops
Scanner input = new Scanner(expression);
String next;
while (input.hasNext()) //Iterator is used (hasNext)
{
if (input.hasNext(UNSIGNED_DOUBLE))
{ // if next input is a number
next = input.findInLine(UNSIGNED_DOUBLE);
numbers.push(new Double(next)); //adding nums to the number stack
}
else
{ //The next input is an operator
next = input.findInLine(CHARACTER);
switch (next.charAt(0))
{
case '+':
case '-':
case '*':
case '/':
operators.push(next.charAt(0)); //adding operators to operator stack
break;
case ')':
evaluateStackTops(numbers, operators);
break;
case '(':
break;
default: //Illegal Character
throw new IllegalArgumentException("Illegal Character");
}
}
}
//This what seems to be throwing the exception but I got this right out of the book
if (numbers.size() != 1)
throw new IllegalArgumentException("Illegal Input");
return numbers.pop( );
}
public static void evaluateStackTops (Stack<Double> numbers, Stack<Character> operators)
{
double operand1 , operand2;
//check that the stacks have enough items, and get the two operands
if ((numbers.size()<2)||(operators.isEmpty())) {
throw new IllegalArgumentException("Illegal Expression");}
operand2 = numbers.pop();
operand1 = numbers.pop();
//carry out an operation based on the operator on top of the stack
for (int i = 0; i < numbers.size(); i++) {
switch (operators.pop()) {
case '+':
numbers.push(operand1 + operand2);
break;
case '-':
numbers.push(operand1 - operand2);
break;
case '*':
numbers.push(operand1 * operand2);
break;
case '/':
numbers.push(operand1 / operand2);
break;
default:
throw new IllegalArgumentException("Illegal Operator");
}
}
public static void main(String[] args) {
//String expression;
//Scanner input = new Scanner(expression);
System.out.println(postFix.postfixEvaluate("(2 3 5 * / )" ));
}
}
Your algorithm is flawed. All it does is build stacks of operators and operands, and then evaluate the expression backwards. That's never going to work.
I don't understand why you're even checking for parentheses. There are no parentheses in postfix expressions, because the conversion from infix to postfix has already removed the parentheses.
Also, there is no need for a stack of operators. The whole idea of postfix is that you can evaluate each operator as you encounter it, and push the result back onto the stack.
The basic algorithm is:
while not end of input
read next token
if token is a number
push on numbers stack
else if token is operator
pop value2 and value1 from stack
result = evaluate value1 <operator> value2
push result to numbers stack
else
invalid input
end while
// at this point, there should be 1 value on numbers stack
So when evaluating 5 2 4 * / 7 -, the sequence is:
push 5
push 2
push 4
// operator * read here
pop 4
pop 2
evaluate 2 * 4
push 8
// operator / read here
pop 8
pop 5
evaluate 5/8
push 0.625
push 7
// operator - read here
pop 7
pop 0.625
evaluate 0.625 - 7
push -6.375
// end of input here
pop final result
private class InputListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
// Create an integer and character stack
Stack<Integer> operandStack = new Stack<Integer>();
Stack<Character> operatorStack = new Stack<Character>();
// User input in input text field
String input = inputTextField.getText();
// Create string tokenizer containing string input
StringTokenizer strToken = new StringTokenizer(input);
// Loop while there are tokens
while (strToken.hasMoreTokens())
{
String i = strToken.nextToken();
int operand;
char operator;
try
{
operand = Integer.parseInt(i);
operandStack.push(operand);
}
catch (NumberFormatException nfe)
{
operator = i.charAt(0);
operatorStack.push(operator);
}
}
// Loop until there is only one item left in the
// operandStack. This one item left is the result
while(operandStack.size() > 1)
{
// Perform the operations on the stack
// and push the result back onto the operandStack
operandStack.push(operate(operandStack.pop(),
operandStack.pop(), operatorStack.pop()));
}
// Display the result as a string in the result text field
resultTextField.setText(Integer.toString(operandStack.peek()));
}
// Sum and product computed
public int operate(Integer operand1, Integer operand2, char operator)
{
switch(operator)
{
case '*':
return operand2 * operand1;
case '/':
return operand2 / operand1;
case '%':
return operand2 % operand1;
case '+':
return operand2 + operand1;
case '-':
return operand2 - operand1;
default:
throw new IllegalStateException("Unknown operator " + operator + " ");
}
}
}
The prefix expression code provided is incorrectly evaluating expressions with more than one operator. The expression: * + 16 4 + 3 1 should evaluate to 80 = ((16 + 4) * (3 + 1)), but instead it evaluates to 128, which I think is evaluating as: ((16 + 4) * (3 + 1) + (16 * 3)). How do I edit the code to correct this problem? Thank you for your help.
In prefix evaluation,Important thing to remember is
operand 1= pop();
operand 2= pop();
and say the operator is -
The value that is pushed is operand 1 - operand 2 and not operand 2 - operand 1
But something else is causing * + 16 4 + 3 1 to evaluate to 128.
I used the following algo for evaluating in java and it works fine
1.Take the prefix expression as a string in a variable with characters separated by single space.
2.Traverse the string from index length-1 to 0
3.If its a number, perform push ,and if its a multidigit number,first obtain the full number and then push it
4.If its an operator then simply do the thing which i mentioned in beginning of the answer.
It is a simple code.
import java.io.*;
import java.util.*;
class PREFIXEVAL
{
public static void main(String []args)throws IOException
{
String p,n="";StringBuffer b;int i,op1,op2;char c;Stack<Integer> s=new Stack<Integer>();
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
System.out.println("enter the prefix expression separated by spaces");
p=br.readLine();
i=p.length()-1;
while(i>=0)
{
c=p.charAt(i);
if(c>=48&&c<=57)
n=n+c;
else if(c==' '&&!n.equals(""))
{/*handles both single and multidigit numbers*/
b=new StringBuffer(n);b.reverse();n=b.toString();
s.push(Integer.parseInt(n));n="";
}
else
{
if(c=='+')
{
op1=s.pop();
op2=s.pop();
s.push(op1+op2);
}
else if(c=='-')
{
op1=s.pop();
op2=s.pop();
s.push(op1-op2);
}
else if(c=='*')
{
op1=s.pop();
op2=s.pop();
s.push(op1*op2);
}
else if(c=='%')
{
op1=s.pop();
op2=s.pop();
s.push(op1%op2);
}
else if(c=='/')
{
op1=s.pop();
op2=s.pop();
s.push(op1/op2);
}
}
i--;
}
System.out.println("the prefix expression evaluates to "+s.peek());
}
}
Here is my code so far:
public class PostfixCalculator {
private Stack<Float> stack;
private float result;
private Boolean isOperator (char op){
boolean operator;
switch (op){
case '+':
case '-':
case '*':
case '/':
case '^':
operator = true;
break;
default:
operator = false;
break;}
return operator;
}
private Boolean isFunction (String func){
String[] functions = {"sin", "cos", "max"};
for (int i=0; i<functions.length; i++){
if (func.equals(functions[i]))
return true; }
return false;
}
private void computeOperator (float op1, float op2, char op){
switch (op){
case '+':
result = op1 + op2;
break;
case '-':
result = op1 - op2;
break;
case '/':
result = op1/op2;
break;
case '*':
result = op1 * op2;
break;
case '^':
result = (float) Math.pow(op1, op2);
break;
default:
break;
}
}
public float calculate(String expr) throws IllegalArgumentException {
result = 0;
String token;
Float makeit;
char operator;
float op1, op2, pushFloat;
StringTokenizer calc=new StringTokenizer(expr);
stack = new Stack<Float>();
while (calc.hasNextToken()){
token=calc.getNextToken();
operator=token.charAt(0);
if (!(this.isOperator(operator))){
if (this.isFunction(token)){
if (token.equals("sin")){
op1=stack.pop();
result = (float) Math.sin(op1);
stack.push(result);
}
else if (token.equals("cos")){
op1=stack.pop();
result = (float) Math.cos(op1);
stack.push(result);
}
else if (token.equals("max")){
op1=stack.pop();
op2=stack.pop();
result=Math.max(op1, op2);
stack.push(result);
}
}
else {
makeit = new Float(token);
pushFloat = makeit.floatValue();
stack.push(pushFloat);
}
}
else {
op1 = stack.pop();
op2 = stack.pop();
computeOperator (op1, op2, operator);
stack.push(result);
}
}
return stack.pop();
}
}
I think I have the basics of it down, but how do I deal with postfix calculations with three digits in a row or more, like for example '2 3 4 * -'? Any help would be appreciated. Thanks in advance!
Yep, a stack. And one can implement a simple stack easily with an array and a counter -- no real need to use a fancy class.
The array would be as large as the most deeply nested expression that you can handle (10 elements should be sufficient for virtually all "real" problems).
Push is update A[i] and increment i. Pop is decrement i and reference A[i]. "8 9 +" is push(8), push(9), pop the top two elements, add them, push the result. Note that operators are never pushed, only operands/results.
'2 3 4 * -' would be push(2), push(3), push(4), pop top two, multiply, push result, pop two, subtract, push result.
"7 6 + cos" would be push(7), push(6), pop two, add, push result, pop one, perform "cos", push result.
Error if you need to pop an element and the counter is zero (eg, "7 +" -- you'd want to pop twice but you can only pop once). Also an error if the user expresses "finished" and there is more than one element in the stack.
Always "display" your top element, as that's the last value pushed or the result.
For a calculator like this, you should use a stack. Every number is a push and every operation has a corresponding action.
st = []
while input:
if isanumber(input.next()): st.push(input.consume())
else: #its an operator
#note this may be wrong for operators that have a specific order
if(input.next() == "+"):
stack.push(stack.pop() + stack.pop())
# more operations
input.consume()
print(st)
And that would be the rough python to do it, in this instance I look ahead a single token before making a decision.
edit:
Probably should have read your code before posting, anyway you must always push back the computed number, also attempt to simplify your code into only "functions" and "numbers" making functions that perform both. Regex is also useful for this sort of thing, such as the http://www.cplusplus.com/reference/std/regex/.