patternjavaMinor
Calculator with order of operations
Viewed 0 times
withoperationsordercalculator
Problem
I am trying to make an additional option in my beginning calculator program, which is based on the
Right now, my only concern is the logic of this task, which I will implement in my program later. Does it make any sense to base such options, which will use a variety of number types, on a simple "looking for brackets" and operations on
```
import java.util.*;
public class OrderOfOperations {
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
String s = scanner.nextLine();
String w = result(s);
System.out.println("Result: "+w);
}
public static String before(String s, int i){ //number before operation mark
String str = s.substring(0,i);
String num = "";
for(int b=str.length()-1;b>=0;b--){
if(b==0 || !Character.isDigit(str.charAt(b-1))&&str.charAt(b-1)!='.'){
num=str.substring(b);
break;
}
}
return num;
}
public static String after(String s, int i){ //number after operation mark
String str = s.substring(i+1);
String num = "";
for(int a=0;a<=str.length();a++){
if(a==str.length() || !Character.isDigit(str.charAt(a))&&str.charAt(a)!='.'){
num=str.substring(0,a);
break;
}
}
return num;
}
public static String result(String s){
char o = '(';
char c = ')';
while(s.contains(Character.toString(o))||s.contains(Character.toString(c))){
String in;
if(s.contains(Character.toString(o))){
System.out.println(s);
in = s.subst
BigDecimal class: the simultaneous solution for the entire operation by order of operations. I want to create methods by myself, however it took me a long time just to create a sketch, and for a moment I wonder if I chose a right way. Right now, my only concern is the logic of this task, which I will implement in my program later. Does it make any sense to base such options, which will use a variety of number types, on a simple "looking for brackets" and operations on
Strings? Does anyone see any flaws in that method?```
import java.util.*;
public class OrderOfOperations {
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
String s = scanner.nextLine();
String w = result(s);
System.out.println("Result: "+w);
}
public static String before(String s, int i){ //number before operation mark
String str = s.substring(0,i);
String num = "";
for(int b=str.length()-1;b>=0;b--){
if(b==0 || !Character.isDigit(str.charAt(b-1))&&str.charAt(b-1)!='.'){
num=str.substring(b);
break;
}
}
return num;
}
public static String after(String s, int i){ //number after operation mark
String str = s.substring(i+1);
String num = "";
for(int a=0;a<=str.length();a++){
if(a==str.length() || !Character.isDigit(str.charAt(a))&&str.charAt(a)!='.'){
num=str.substring(0,a);
break;
}
}
return num;
}
public static String result(String s){
char o = '(';
char c = ')';
while(s.contains(Character.toString(o))||s.contains(Character.toString(c))){
String in;
if(s.contains(Character.toString(o))){
System.out.println(s);
in = s.subst
Solution
Unfortunately, your algorithm is not correct. It evaluates an expression
-
You shouldn't make arbitrary assumptions. The algorithm you are using is not a well-known one, it is rather complex so it is not obvious whether it is correct or not, but you probably did not prove its correctness. For instance, you made an assumption that we can remove the first opening parenthesis and evaluate the part of the expression which goes after it separately. Is this assumption based on something? Did you try to figure out why it is correct? As you can see, it turned out to be incorrect. Proofs give you confidence in the logic of your solution.
-
You can use already existing algorithms. Arithmetic expressions evaluation is a well-studied topic. There is an efficient shunting-yard algorithm, which runs in linear time and is proven to be correct. Reinventing a non-trivial algorithm is not a good idea(unless you deliberately decide to do it as an exercise, but in this case you should be able to reason about the correctness of your solution).
-
Test your code in a systematic manner. Writing unit-tests is a good practice. The counterexample to your algorithm is rather short and simple, so you probably could have spotted that it is not correct if you had tested your code carefully.
1-(1+1)+1 to -2.0, but it is clear that the right answer is zero. It is not an implementation bug. The logic itself is wrong. So what can be done to avoid(or, at least, to minimize the risk of) ending up with an incorrect algorithm?-
You shouldn't make arbitrary assumptions. The algorithm you are using is not a well-known one, it is rather complex so it is not obvious whether it is correct or not, but you probably did not prove its correctness. For instance, you made an assumption that we can remove the first opening parenthesis and evaluate the part of the expression which goes after it separately. Is this assumption based on something? Did you try to figure out why it is correct? As you can see, it turned out to be incorrect. Proofs give you confidence in the logic of your solution.
-
You can use already existing algorithms. Arithmetic expressions evaluation is a well-studied topic. There is an efficient shunting-yard algorithm, which runs in linear time and is proven to be correct. Reinventing a non-trivial algorithm is not a good idea(unless you deliberately decide to do it as an exercise, but in this case you should be able to reason about the correctness of your solution).
-
Test your code in a systematic manner. Writing unit-tests is a good practice. The counterexample to your algorithm is rather short and simple, so you probably could have spotted that it is not correct if you had tested your code carefully.
Context
StackExchange Code Review Q#82973, answer score: 4
Revisions (0)
No revisions yet.