I\'m looking for a way to shorten this code up and avoid repeating code and if statements. What I\'m doing is creating a calculator that searches strings for operators &quo
You could write an AbstractCalculationOperation
class with execute
method, with Add
, Subtract
, etc extending it.
Then, just parse leftHand
, rightHand
, and calculationOperation
and run calculationOperation.execute( rightHand, leftHand )
.
public interface CalculationOperation {
double calculate ( double lh, double rh );
long calculate ( long lh, long rh );
}
public class Add implements CalculationOperation {
public static final CalculationOperation INSTANCE = new Add();
public double calculate ( double rh, double lh ) { return lh + rh; }
public long calculate ( long rh, long lh ) { return lh + rh; }
}
And then:
int lh = exp.substring(0, i);
int rh = exp.substring(i+1);
CalculationOperation op;
switch( exp.charAt(i) ) {
case '*': op = Multiply.INSTANCE; break;
case '/': op = Divide.INSTANCE; break;
case '+': op = Add.INSTANCE; break;
case '-': op = Subtract.INSTANCE; break;
}
newResult = op.calculate( rh, lh );
primeResult = newResult;
System.out.println(primeResult);
Alternate enum variant:
public enum Calculation {
ADD('+') {
public int calculate( int lhs, int rhs ) { return lhs + rhs; }
public long calculate( long lhs, long rhs ) { return lhs + rhs; }
public float calculate( float lhs, float rhs ) { return lhs + rhs; }
public double calculate( double lhs, double rhs ) { return lhs + rhs; }
},
SUBTRACT('-') {
public int calculate( int lhs, int rhs ) { return lhs - rhs; }
public long calculate( long lhs, long rhs ) { return lhs - rhs; }
public float calculate( float lhs, float rhs ) { return lhs - rhs; }
public double calculate( double lhs, double rhs ) { return lhs - rhs; }
},
MULTIPLY('*') {
public int calculate( int lhs, int rhs ) { return lhs * rhs; }
public long calculate( long lhs, long rhs ) { return lhs * rhs; }
public float calculate( float lhs, float rhs ) { return lhs * rhs; }
public double calculate( double lhs, double rhs ) { return lhs * rhs; }
},
DIVIDE('/') {
public int calculate( int lhs, int rhs ) { return lhs / rhs; }
public long calculate( long lhs, long rhs ) { return lhs / rhs; }
public float calculate( float lhs, float rhs ) { return lhs / rhs; }
public double calculate( double lhs, double rhs ) { return lhs / rhs; }
};
private final char textValue;
Calculation ( char textValue )
{
this.textValue = textValue;
}
public abstract int calculate ( int lht, int rhs );
public abstract long calculate ( long lht, long rhs );
public abstract float calculate ( float lht, float rhs );
public abstract double calculate ( double lht, double rhs );
public static Calculation fromTextValue( char textValue ) {
for( Calculation op : values() )
if( op.textValue == textValue )
return op;
throw new IllegalArgumentException( "Unknown operation: " + textValue );
}
}
and then:
int lh = exp.substring(0, i);
int rh = exp.substring(i+1);
Calculation op = Calculation.fromTextValue( exp.substring(i,1) );
newResult = op.calculate( lh, rh );
primeResult = newResult;
System.out.println(primeResult);
It's pretty simple how to avoid too much code repetition:
Integer op1= Integer.parseInt(exp.substring(0, i);
Integer op2=Integer.parseInt(exp.substring(i+1, exp.length()));
if(exp.charAt(i)=='*') {
newResult=op1 * op2;
} else
....
primeResult = newResult;
System.out.println(primeResult);
But to do something more general, robust and useful, with arbitrary nesting levels, you should use some real parser. For example.
Here's a snippet:
public static void main(String[] args) {
float primeResult;
String exp = "4-2";
int i = 1;
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("JavaScript");
char[] myVar = new char[] { '*', '/', '-', '+' };
for (int myVarCtr = 0; myVarCtr < myVar.length; myVarCtr++) {
if (exp.charAt(i) == myVar[myVarCtr]) {
try {
primeResult = Float.parseFloat(engine.eval(
(Integer.parseInt(exp.substring(0, i)))
+ Character.toString(myVar[myVarCtr])
+ (Integer.parseInt(exp.substring(i + 1,
exp.length())))).toString());
System.out.println(primeResult);
} catch (ScriptException e) {
e.printStackTrace();
}
}
}
}
For changing the code you could use a switch statement and putting some of the redundant code before or after the switch.
int left = Integer.parseInt(exp.substring(0,i));
int right = Integer.parseInt(exp.substring(i+1,exp.length()));
switch(exp.charAt(i)){
case '*':
primeResult = left * right;
break;
case '/':
...
break;
case '+':
...
break;
case '-':
...
break;
default:
... // Error Handling.
}
System.out.println(primeResult);
Shorten the code by grabbing the variables separately from doing the operation. This will not reduce your "if" statements, but it will drastically reduce the line numbers.
Don't do multiple variables until you understand trees... I've never worked with them personally, but I think "expression trees" are what you'll be after. (note: I just checked on google, yep, Expression Trees)
There's no need of switch
statements and complex hierrachies of classes.
In order to simplify and shorten your code and calculate simple and complex expressions (represented as String
objects), you can use the Java's JavaScript API
and it's ScriptEngine
class, which basically simulates a JavaScript
console.
import javax.script.ScriptEngineManager;
import javax.script.ScriptEngine;
public class MyClass{
public static void main(String[] args) throws Exception {
// create a script engine manager
ScriptEngineManager factory = new ScriptEngineManager();
// create a JavaScript engine
ScriptEngine engine = factory.getEngineByName("JavaScript");
// evaluate JavaScript code from String
System.out.println(engine.eval("(5+10)*2/3"));
}
}
This will output: 10.0