Java:Evaluation of Mathematical Expression only from left to right
I have written a Java program which evaluates a mathematical expression from left to right (no precedence, just left to right). However, I'm not getting the desired output.
import java.util.*;
public class Evaluation {
//private static final char[] validOperators = {'/','*','+','-'};
private Evaluation()
{
/* Using a private contructor to prevent instantiation
Using class as a simple static utility class
*/
}
private static int evaluate(String leftSide, char oper, String rightSide)
throws IllegalArgumentException
{
System.out.println("Evaluating: " + leftSide + " (" + oper + ") " + rightSide);
int total = 0;
int leftResult = 0;
int rightResult = 0;
String originalString =leftSide;
int operatorLoc = findOperatorLocation(leftSide);
leftSide = leftSide.substring(0,operatorLoc);
rightSide = originalString.substring(operatorLoc+1,operatorLoc+2);
String remainingString = originalString.substring(operatorLoc+2,originalString.length());
System.out.println("leftSide -->"+leftSide);
System.out.println("rightSide -->"+rightSide);
System.out.println("remainingString --->"+remainingString);
try {
leftResult = Integer.parseInt(leftSide);
} catch(Exception e) {
throw new IllegalArgumentException(
"Invalid value found in portion of equation: "
+ leftSide);
}
try {
rightResult = Integer.parseInt(rightSide);
} catch(Exception e) {
throw new IllegalArgumentException(
"Invalid value found in portion of equation: "
+ rightSide);
}
System.out.println("Getting result of: " + leftResult + " " + oper + " " + rightResult);
switch(oper)
{
case '/':
total = leftResult / rightResult; break;
case '*':
total = leftResult * rightResult; break;
case '+':
total = leftResult + rightResult; break;
case '开发者_StackOverflow-':
total = leftResult - rightResult; break;
default:
throw new IllegalArgumentException("Unknown operator.");
}
System.out.println("Returning a result of: " + total);
String totally = String.valueOf(total)+remainingString;
return evaluate(totally,findCharacter(totally),remainingString);
}
private static int findOperatorLocation(String string) {
int index = -1;
index = string.indexOf(string.substring(1,2));
if(index >= 0) {
return index;
}
return index;
}
private static char findCharacter(String string) {
char c='\u0000';
int index = -1;
index = string.indexOf(string.substring(1,2));
if(index >= 0){
c = string.charAt(index);
return c;
}
return c;
}
public static int processEquation(String equation)
throws IllegalArgumentException
{
return evaluate(equation,'+',"0");
}
public static void main(String[] args)
{
//String usage = "Usage: java MathParser equation\nWhere equation is a series"
// + " of integers separated by valid operators (+,-,/,*)";
//if(args.length < 1 || args[0].length() == 0)
// System.out.println(usage);
Scanner input = new Scanner(System.in);
System.out.print("Enter the equation to be evaluated ");
String equation = (String)input.next();
int result = Evaluation.processEquation(equation);
System.out.println("The result of your equation ("
+ equation + ") is: " + result);
//catch(IllegalArgumentException iae)
//{
// System.out.println(iae.getMessage() + "\n" + usage);
//}
}
}
Here is the input I'm trying to use, and what I expect:
3+5*2-5
=>8*2-5 =>16-5 =>Expected Output :11
But I'm getting this output:
Enter the equation to be evaluated 3+5*2-5
Evaluating: 3+5*2-5 (+) 0 leftSide -->3 rightSide -->5 remainingString --->*2-5 Getting result of: 3 + 5 Returning a result of: 8 Evaluating: 8*2-5 (*) *2-5 leftSide -->8 rightSide -->2 remainingString --->-5 Getting result of: 8 * 2 Returning a result of: 16 Evaluating: 16-5 (6) -5 leftSide -->1 rightSide -->- remainingString --->5 Exception in thread "main" java.lang.IllegalArgumentException: Invalid value found in portion of equation: - at Evaluation.evaluate(Evaluation.java:49) at Evaluation.evaluate(Evaluation.java:70) at Evaluation.evaluate(Evaluation.java:70) at Evaluation.processEquation(Evaluation.java:98) at Evaluation.main(Evaluation.java:112)
I'm unable to make my program generic for any equation entered.
I appreciate any help you can provide. Please note this is not a homework question.Your findOperatorLoc is incorrect.
It automatically assumes that the operator is the second character.
index = string.indexOf(string.substring(1,2));
EDIT -- A cleaner implementation of this might be like so. split your equation based on operators and then based on operands. You will be left with 2 arrays , one with all the operators and one with all operands.
String[] aa = op.split("[*+-]");
for ( String s : aa )
System.out.println(s);
String[] bb = op.split("[0-9]");
for ( String s : bb )
System.out.println(s);
// Now loop through the operand array and apply the necessary oeprator in order
for ( int i = 0 ; i < aa.length ; i++ ) {
int val = applyOperator(Integer.parseInt(aa[i]), Integer.parseInt(aa[i+1]), bb[i]);
}
This is pseudocode only .. I will leave you to implement the applyOperator method
You are getting this error because rightSide
has the String value "-" and you are attempting to do Integer.parseInt()
on it.
Your code for determining rightSide
as well as the method findOperatorLocation
both assume that all numbers and intermediary results have only one digit. So you run into problems as soon as you have an intermediarey result (16) that has two digits.
You have a small bug in your program where you correctly consider digits to be numbers, but you incorrectly consider all numbers to only consist of one digit.
Since a number only consists of one digit, when handling "16-5" the values are
left side = "1"
operator = "6"
right side = "-"
rest of string = "5"
If you improved your "left side" routine, then it would recogonize the entire left side as
left side = "16"
operator = "-"
right side = "5"
rest of string = empty or "", depending on how you code it
Keep in mind that if you have a bug on the "left side" detection where you assume that all numbers are one digit long, odds are good you have a bug on the "right side" detection where you assume that all numbers are one digit long.
As others have pointed out, you have an issue with findOperatorLocation
, but let me attempt to reframe their suggestions using the pattern I see. Essentially what you are trying to build here is an interpreter for a programming language whose only statements are the mathematical operations you have defined.
Since you are building a programming language interpreter there are 3 steps that your evaluate
method goes through 1) scanning & parsing 2) creation of intermediate code 3) execution. The issue in your program lies in the parsing step. If you were to exact the parsing functionality to a separate function, and run test strings through that function, then it would be easier for you to see what is going wrong. This is mostly a design problem; you are trying to verify all three steps (scanning/parsing, code generation, and execution) through the evaluate
function. This results in a large surface area to debug.
If you are going to continue to evolve the statements that your program supports, I would recommend that you review some resources on parsing such as: https://www.youtube.com/watch?v=LCslqgM48D4&ab_channel=NextDayVideo Happy Coding!
精彩评论