patternjavaMinor
Optimizing "simplifier"
Viewed 0 times
optimizingsimplifierstackoverflow
Problem
Basically, I'm trying to make a Simplifier that can take inputs in the form of a
Here are some outputs:
I'd be grateful if anyone would comment
String and print out the solution step-by-step. Now that I've got it working, I think it has some cleanliness issues.public static void test(String eqn) {
char[] order = { '^', '*', '/', '+'}; //order of precendece
int found, i, j;
eqn = eqn.replace("-", "+-"); //Subtracting = Adding (-)ve number.
eqn = eqn.replace(" ", ""); //Spaces can cause a lot of trouble.
String eqnC, left, right;
System.out.println("=>\t"+eqn);
for(char op : order) {
while ((found = eqn.indexOf(op)) > -1) {
left = eqn.substring(0, found);
right = eqn.substring(found + 1);
//keep 'walking' up and down the String till a non-number encoutered.
for( i = left.length() - 1; i >= 0; i--)
if(!isPONumber(left.charAt(i)))
break;
for( j = 0; j < right.length(); j++)
if(!isPONumber(right.charAt(j)))
break;
double lV = Double.parseDouble(left.substring(++i)); //left operand
double rV = Double.parseDouble(right.substring(0, j)); //right operand
eqn = left.substring(0, i) + putV(lV, rV, op) + right.substring(j);
System.out.println("=\t" + eqn);
}
}
}
private static String putV(double a, double b, char op) {
switch(op) {
case '^': return Math.pow(a, b) + "";
case '/': return (a / b) + "";
case '*': return (a * b) + "";
case '+': return (a + b) + "";
}
return null;
}
/*
* Limit (for now) : decimal support.
*/
private static boolean isPONumber(char c) {
return Character.isDigit(c) || c == '.' || c == '-';
}Here are some outputs:
=> 2*84/6+7^2
= 2*84/6+49.0
= 168.0/6+49.0
= 28.0+49.0
= 77.0
=> 3^3/3^2
= 27.0/3^2
= 27.0/9.0
= 3.0
=> 400^0.5
= 20.0I'd be grateful if anyone would comment
Solution
Algorithm
The algorithm works well enough. You have captured the essence of the problem in your code, and reading your code it is apparent what it does, and why.
This is a good thing. It is not very often that the intent of the code is so easy to discern.
The draw-back of your algorithm is that it is not going to be able to support the more esoteric operations like parenthesis e.g.
Keeping the equation as a string is convenient for some things, but i would have preferred to see the process broken down in to components, for example, a parse step could break the input down to
Code Style
You should read through the Code Style Guidelines for Java.
This code, for example, has a number of faults:
It should rather look something like:
Notes:
Double.parseDouble
The exception thrown does not give great deals of information about why the number is not valid.
I always recommend wrapping Double.parseDouble (and
I often have a helper function like:
The algorithm works well enough. You have captured the essence of the problem in your code, and reading your code it is apparent what it does, and why.
This is a good thing. It is not very often that the intent of the code is so easy to discern.
The draw-back of your algorithm is that it is not going to be able to support the more esoteric operations like parenthesis e.g.
( 123 - 45 ) ^ 2 .... That sort of support will require a preprocessing step.Keeping the equation as a string is convenient for some things, but i would have preferred to see the process broken down in to components, for example, a parse step could break the input down to
List eqnParts = parse(eqn). at the same time, it could be trimming the white-space. Then, you just need to scan the List and find 3 items separated by the highest precedence operator, and swap all three with the resulting value.Code Style
You should read through the Code Style Guidelines for Java.
This code, for example, has a number of faults:
for( i = left.length() - 1; i >= 0; i--)
if(!isPONumber(left.charAt(i)))
break;
for( j = 0; j < right.length(); j++)
if(!isPONumber(right.charAt(j)))
break;It should rather look something like:
for (int i = left.length() - 1; i >= 0; i--) {
if(!isPONumber(left.charAt(i))) {
break;
}
}
for (int j = 0; j < right.length(); j++) {
if(!isPONumber(right.charAt(j))) {
break;
}
}Notes:
- declare
int iandint jinside the loop.
- space after the keyword
for.
- braces even for '1-liner' conditional statements.
Double.parseDouble
Double.parseDouble() throws the unchecked exception NumberFormatException.The exception thrown does not give great deals of information about why the number is not valid.
I always recommend wrapping Double.parseDouble (and
Integer.parseInteger(), etc.) in a try-catch that reports what value was parsed, as well as the exception that was thrown. Otherwise debugging is a pain.I often have a helper function like:
public static final double parseDouble(String value) {
try {
return Double.parseDouble(value);
} catch (NumberFormatException nfe) {
throw new IllegalArgumentException("Unable to Double.parseDouble(" + value + ")", nfe);
}
}Code Snippets
for( i = left.length() - 1; i >= 0; i--)
if(!isPONumber(left.charAt(i)))
break;
for( j = 0; j < right.length(); j++)
if(!isPONumber(right.charAt(j)))
break;for (int i = left.length() - 1; i >= 0; i--) {
if(!isPONumber(left.charAt(i))) {
break;
}
}
for (int j = 0; j < right.length(); j++) {
if(!isPONumber(right.charAt(j))) {
break;
}
}public static final double parseDouble(String value) {
try {
return Double.parseDouble(value);
} catch (NumberFormatException nfe) {
throw new IllegalArgumentException("Unable to Double.parseDouble(" + value + ")", nfe);
}
}Context
StackExchange Code Review Q#44726, answer score: 4
Revisions (0)
No revisions yet.