I am creating a Calculator with + - * / and %(Modulus). The basic calculator is working but I am now wondering how I should prioritise multiplication and division before addition and substraction. Can't really figure it out.
I need to write a whole string which will be converted to a double and then back to string for printout.
example: 3+3-4*8+5/6+5
Here is my code below
public String calculateExpression(String expression){
double dres = 0.0;
String[] split = expression.split("(?=[*/+-])|(?<=[*/+-])");
dres = Double.parseDouble(split[0]);
for (int i = 1; i < split.length; i+= 2) {
String op = split[i];
double val = Double.parseDouble(split[i+1]);
switch (op) {
case "+":
dres = Addition(dres, val);
break;
case "-":
dres = Subtraction(dres, val);
break;
case "*":
dres = Multiplication(dres, val);
break;
case "/":
dres = Division(dres, val);
break;
default:
break;
}
}
String res = Double.toString(dres);
return res;
}
public double Addition(double d1,double d2) {
return d1+d2;
}
public double Subtraction(double d1, double d2) {
return d1-d2;
}
public double Multiplication(double d1, double d2) {
return d1*d2;
}
public double Division(double d1, double d2) {
return d1/d2;
}
public double Modulus(double d1, double d2) {
return d1%d2;
}
What you can do is scan for the right-most occurrence of a * or /, and split the String into two parts (to the left of the symbol and to the right of the symbol). Then, call your own method to determine the values of either side; then perform the multiplication/division operation.
If there isn't any * or /, you can do the same thing for + and -.
If there isn't any operator at all, then just return the number.
Maybe try something like a brute force approach:
public String calculateExpression(String expression){
double dres = 0.0;
String[] split = expression.split("(?=[*/+-])|(?<=[*/+-])");
dres = Double.parseDouble(split[0]);
for (int i = 1; i < split.length; i+= 2) {
String op = split[i];
double val = Double.parseDouble(split[i+1]);
switch (op) {
if(case == "+" or case == "*") {
case "+":
dres = Addition(dres, val);
break;
case "*":
dres = Multiplication(dres, val);
break;
}
else {
case "-":
dres = Subtraction(dres, val);
break;
case "/":
dres = Division(dres, val);
break;
}
default:
break;
}
}
String res = Double.toString(dres);
return res; }
Not sure if the code is correct, but you get the gist.
This is a classic application of the Interpreter Pattern.
Unfortunately, I had trouble understanding what exactly the example on wikipedia is doing...
But the solution definitely has to do with stacks (called ArrayDeque in Java).
Related
I made a little random math generator, which gives out 2 random numbers and a random operator but when I call my check result method in my ok button, I always get the "Errado" ("Wrong") string which means it's not properly comparing the value of the textfield with the result of whatever math problem was presented. Leaving relevent code from both classes down here with comments on where I'm having issues and 2 for ease of understanding. Help's appreciated!
public class geraAritmetica {
ArrayList<Integer> nums = new ArrayList();
int a;
char ops = '?';
int max = 10;
int min = 1;
int range = max - min + 1;
int res;
Random r = new Random();
public int gerarNums(){
for(int i = 0; i<10; i++){
a = (int) (Math.random()*range) + min;
nums.add(a);
}
return a;
}
public char gerarOps(){
switch(r.nextInt(4)){
case 1 : ops = '+';
res = nums.get(0) + nums.get(1);
break;
case 2: ops = '-';
res = nums.get(0) - nums.get(1);
break;
case 3: ops = '*';
res = nums.get(0) * nums.get(1);
break;
case 4: ops = '/';
res = nums.get(0) / nums.get(1);
break;
default: ops = '+';
res = nums.get(0) + nums.get(1);
break;
}
return ops;
}
public boolean checkRes(){ //everytime I call this method always get the same string "Errado" ("Wrong") in the label.
if(Integer.parseInt(FrameEnsinoAritmetica.jTextField1.getText()) == res){
FrameEnsinoAritmetica.jLabel2.setText("Correto!");
return true;
}
else FrameEnsinoAritmetica.jLabel2.setText("Errado!");
return false;
}
}
public class FrameEnsinoAritmetica extends javax.swing.JFrame {
geraAritmetica a = new geraAritmetica(); //creating object of class at the start of my JFrame class
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) { //generating numbers and operator (it prints fine in another label)
int b = a.gerarNums();
int c = a.gerarNums();
char s = a.gerarOps();
jLabel1.setText(b + " " +s+ " " + c);
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
a.checkRes(); //everytime I call this method always get the same string "Errado" ("Wrong") in the label.
}
You seem to be referencing to the FrameEnsinoAritmetica class directly not the actual instance of your FrameEnsinoAritmetica jFrame that you see on screen. For example, using this in another class will not reference to the frame that you see on screen:
String text = FrameEnsinoAritmetica.jTextField1.getText();
But using this would work:
String text = yourInstanceOfEnsinoAritmetica.jTextField1.getText();
To fix this we could pass the current instance of the FrameEnsinoAritmetica that is shown on screen into the checkRes method, which we do by modifying checkRes like so, and inside the method we replace FrameEnsinoAritmetica with frame to refer to the current instance:
public boolean checkRes(FrameEnsinoAritmetica frame){ //everytime I call this method always get the same string "Errado" ("Wrong") in the label.
if(Integer.parseInt(frame.jTextField1.getText()) == res){
frame.jLabel2.setText("Correto!");
return true;
}
else frame.jLabel2.setText("Errado!");
return false;
}
Then we just update the jButton1ActionPerformed method to pass this which is the current instance of FrameEnsinoAritmetica into the updated checkRes method:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
a.checkRes(this); //everytime I call this method always get the same string "Errado" ("Wrong") in the label.
}
Fix part 2 (for res not being calculated properly)
public class FrameEnsinoAritmetica extends javax.swing.JFrame {
geraAritmetica a = new geraAritmetica();
public static int b;
public static int c;
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
b = a.gerarNums();
c = a.gerarNums();
char s = a.gerarOps(this);
jLabel1.setText(b + " " +s+ " " + c + " ");
}
public class geraAritmetica {
ArrayList<Integer> nums = new ArrayList();
int a;
char ops = '?';
int max = 10;
int min = 1;
int range = max - min + 1;
public static int res;
Random r = new Random();
public int gerarNums(){
for(int i = 0; i<10; i++){
a = (int) (Math.random()*range) + min;
nums.add(a);
}
return a;
}
public char gerarOps(FrameEnsinoAritmetica frame){
switch(r.nextInt(4)){
case 1 : ops = '+';
res = frame.b + frame.c; //checking both variables directly from JFrame class instead of getting through index from ArrayList.
break;
case 2: ops = '-';
res = res = frame.b - frame.c;
break;
case 3: ops = '*';
res = frame.b * frame.c;
break;
case 4: ops = '/';
res = frame.b / frame.c;
break;
default: ops = '+';
res = frame.b + frame.c;
break;
}
return ops;
}
public boolean checkRes(FrameEnsinoAritmetica frame){
if(Integer.parseInt(frame.jTextField1.getText()) == res){
frame.jLabel2.setText("Correto!");
return true;
}
else frame.jLabel2.setText("Errado!");
return false;
}
}
This may be a relatively simple question, but why is my program getting this error:Expression.java:93: error: reached end of file while parsing
}
I have tried following multiple guides online, like opening and closing my classes correctly, but unfortunately I still seem to be getting this error.
Here is my code in case this helps:
public class Expression {
private static final String SPACE = " ";
private static final String PLUS = "+";
private static final String MINUS = "-";
public static int rank(String operator) {
switch (operator) {
case "^": //5
return 3;
case "*":
case "/":
return 2;
case PLUS:
case MINUS: //2
return 1;
default:
return -1;
}
}
public static boolean isOperator(String token) { //4
if (rank(token) > 0){
return true;
}
return false;
}
public static int applyOperator(String operator,int op1,int op2){ //7
switch (operator) {
case PLUS:
return op1+op2;
case MINUS:
return op1-op2;
case "*":
return op1*op2;
case "/":
return op1/op2;
default:
return -1;
}
}
public static String toPostfix(String infixExpr) {
StringBuilder output = new StringBuilder();
Stack<String> operators = new ArrayStack<>();
for (String token: infixExpr.split("\\s+")) {
if (isOperator(token)) { // operator //4
// pop equal or higher precedence
while (!operators.isEmpty() &&
rank(operators.peek()) >= rank(token)) {
output.append(operators.pop() + SPACE);
}
operators.push(token);
} else { // operand
output.append(token + SPACE);
}
}
while (!operators.isEmpty()) {
output.append(operators.pop() + SPACE);
}
return output.toString();
}
public class PostFixTest {
public static int evalPostfix(String infixExpr) {
Stack <String> s = new ArrayStack<String>();
String operand = null;
for(int i = 0; i < infixExpr.length(); i++) {
if (Character.isDigit(infixExpr.charAt(i)))
s.push(infixExpr.charAt(i) + "");
else {
if (s.size() > 1) {
int value1 = Integer.parseInt(s.pop());
int value2 = Integer.parseInt(s.pop());
s.push(applyOperator(infixExpr.charAt(i) + "", value1, value2) + "");
}
}
}
return s.pop();
}
}
public static void main(String[] args) {
System.out.println(rank("/"));
String infix = "a * b * c + d ^ e / f";
System.out.println(toPostfix(infix));
System.out.print("Using applyOperator method, 7 * 3 = ");
System.out.println(applyOperator("*", 3, 7));
System.out.print("Using applyOperator method, 50 + 12 = ");
System.out.println(applyOperator("+", 50, 12));
}
You are losing right } in your code last. like:
...
public static void main(String[] args) {
System.out.println(rank("/"));
String infix = "a * b * c + d ^ e / f";
System.out.println(toPostfix(infix));
System.out.print("Using applyOperator method, 7 * 3 = ");
System.out.println(applyOperator("*", 3, 7));
System.out.print("Using applyOperator method, 50 + 12 = ");
System.out.println(applyOperator("+", 50, 12));
}
} // you lost this bracket.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I wrote a simple calculation program. I want users to enter their request as 12+12 and return the answer. I used StringTokenizer, but I got an error and it doesn't show me any result. There was a mention that Calc is a superclass and MinusCalc and PlusCalc are subclasses. Does anyone have any idea?
void inputLineData() { // This is just the function that use for this case
System.out.println(" Plz enter your all numbers");
String strAll = key.next();
StringTokenizer st = new StringTokenizer(strAll);
int n1 = Integer.parseInt(st.nextToken());
String str = st.nextToken();
int n2 = Integer.parseInt(st.nextToken());
switch (str.charAt(0)) {
case '+':
PlusCalc P = new PlusCalc(n1, n2);
listCalc[indexCalc] = P;
indexCalc++;
break;
case '-':
MinusCalc M = new MinusCalc(n1, n2);
listCalc[indexCalc] = M;
indexCalc++;
break;
default:
System.out.println("Error!");
}
}
And this is MinusCalc class:
public class MinusCalc extends Calc {
#Override
public int func(){
return n1 - n2 ;
}
public MinusCalc(int n1, int n2) {
super(n1, n2);
}
}
And this is PlusCalc class:
public class PlusCalc extends Calc {
#Override
public int func(){
return n1 + n2;
}
public PlusCalc(int n1, int n2) {
super(n1, n2);
}
}
And this is Calc class:
public abstract class Calc {
public Calc(int n1, int n2) { // constructor with parameters!!
this.n1 = n1;
this.n2 = n2;
}
int n1,n2;
public abstract int func();
}
Assuming your input is correct the following might help you (if you have more operators just append to the list). The true in the parameter means you want to use the given operator as a delimiter as well as an operator, meaning it will be returned as a token too.
StringTokenizer st = new StringTokenizer(strAll, "+-*/", true);
if (st.countTokens() == 3) {
int operand1 = Integer.parseInt(st.nextToken().trim());
String operator = st.nextToken();
int operand2 = Integer.parseInt(st.nextToken().trim());
switch (operator.charAt(0)) {
case '+':
PlusCalc P = new PlusCalc(operand1, operand2);
listCalc[indexCalc] = P;
indexCalc++;
break;
case '-':
MinusCalc M = new MinusCalc(operand1, operand2);
listCalc[indexCalc] = M;
indexCalc++;
break;
default:
System.out.println("Error!");
}
}
NOTE: try to use another option mentioned in the comments instead of StringTokenizer if you have not to.
This question already has answers here:
Converting Roman Numerals To Decimal
(30 answers)
Closed 9 years ago.
Trying to write program to read in a string of characters that represent a Roman numeral (from user input) and then convert it to Arabic form (an integer). For instance, I = 1, V = 5, X = 10 etc.
Basically, the constructor that takes a parameter of type String must interpret the string (from user input) as a Roman numeral and convert it to the corresponding int value.
Is there an easier way to solve this besides the below in progress (which isn't compiling as yet):
import java.util.Scanner;
public class RomInt {
String roman;
int val;
void assign(String k)
{
roman=k;
}
private class Literal
{
public char literal;
public int value;
public Literal(char literal, int value)
{
this.literal = literal;
this.value = value;
}
}
private final Literal[] ROMAN_LITERALS = new Literal[]
{
new Literal('I', 1),
new Literal('V', 5),
new Literal('X', 10),
new Literal('L', 50),
new Literal('C', 100),
new Literal('D', 500),
new Literal('M', 1000)
};
public int getVal(String s) {
int holdValue=0;
for (int j = 0; j < ROMAN_LITERALS.length; j++)
{
if (s.charAt(0)==ROMAN_LITERALS[j].literal)
{
holdValue=ROMAN_LITERALS[j].value;
break;
} //if()
}//for()
return holdValue;
} //getVal()
public int count()
{
int count=0;
int countA=0;
int countB=0;
int lastPosition = 0;
for(int i = 0 ; i < roman.length(); i++)
{
String s1 = roman.substring(i,i+1);
int a=getVal(s1);
countA+=a;
}
for(int j=1;j<roman.length();j++)
{
String s2= roman.substring(j,j+1);
String s3= roman.substring(j-1,j);
int b=getVal(s2);
int c=getVal(s3);
if(b>c)
{
countB+=c;
}
}
count=countA-(2*countB);
return count;
}
void disp()
{
int result=count();
System.out.println("Integer equivalent of "+roman+" = " +result);
}
public static void main(String[] args)
{
Scanner keyboard = new Scanner(System.in);
System.out.print("Please enter Roman Symbol:");
String s = keyboard.nextLine();
RomInt();
}
}
Roman numerals/Decode Example:
class Roman {
private static int decodeSingle(char letter) {
switch (letter) {
case 'M':
return 1000;
case 'D':
return 500;
case 'C':
return 100;
case 'L':
return 50;
case 'X':
return 10;
case 'V':
return 5;
case 'I':
return 1;
default:
return 0;
}
}
public static int decode(String roman) {
int result = 0;
String uRoman = roman.toUpperCase(); //case-insensitive
for (int i = 0; i < uRoman.length() - 1; i++) {//loop over all but the last character
if (decodeSingle(uRoman.charAt(i)) < decodeSingle(uRoman.charAt(i + 1))) {
result -= decodeSingle(uRoman.charAt(i));
} else {
result += decodeSingle(uRoman.charAt(i));
}
}
result += decodeSingle(uRoman.charAt(uRoman.length() - 1));
return result;
}
public static void main(String[] args) {
System.out.println(decode("MCMXC")); //1990
System.out.println(decode("MMVIII")); //2008
System.out.println(decode("MDCLXVI")); //1666
}
}
Use enum, for easy and simple solution. At first define the decimal equivalent weight at roman.
enum Roman{
i(1),iv(4),v(5), ix(9), x(10);
int weight;
private Roman(int weight) {
this.weight = weight;
}
};
This is the method to convert decimal to roman String.
static String decToRoman(int dec){
String roman="";
Roman[] values=Roman.values();
for (int i = values.length-1; i>=0; i--) {
while(dec>=values[i].weight){
roman+=values[i];
dec=dec-values[i].weight;
}
}
return roman;
}
You can try using a Hashmap to store the roman numerals and equivalent arabic numerals.
HashMap test = new HashMap();
test.add("I",1);
test.add("V",5);
test.add("X",10);
test.add("L",50);
test.add("C",100);
test.add("D",500);
test.add("M",1000);
//This would insert all the roman numerals as keys and their respective arabic numbers as
values.
To retrieve respective arabic numeral one the input of the user, you can use following peice of code:
Scanner sc = new Scanner(System.in);
System.out.println(one.get(sc.next().toUpperCase()));
//This would print the respective value of the selected key.This occurs in O(1) time.
Secondly,
If you only have these set of roman numerals, then you can go for simple switch case statement.
switch(sc.next().toUpperCase())
{
case 'I' :
System.out.println("1");
break;
case 'V'
System.out.println("5");
break;
.
.
.
& so on
}
Hope this helps.
How about this:
public static int convertFromRoman(String roman) {
Map<String, Integer> v = new HashMap<String, Integer>();
v.put("IV", 4);
v.put("IX", 9);
v.put("XL", 40);
v.put("CD", 400);
v.put("CM", 900);
v.put("C", 100);
v.put("M", 1000);
v.put("I", 1);
v.put("V", 5);
v.put("X", 10);
v.put("L", 50);
v.put("D", 500);
int result = 0;
for (String s : v.keySet()) {
result += countOccurrences(roman, s) * v.get(s);
roman = roman.replaceAll(s, "");
}
return result;
}
public static int countOccurrences(String main, String sub) {
return (main.length() - main.replace(sub, "").length()) / sub.length();
}
Not sure I've got all possible combinations as I'm not an expert in roman numbers. Just make sure that the once where you substract come first in the map.
Your compilation issue can be resolved with below code. But surely its not optimized one:
public static void main(String[] args)
{
Scanner keyboard = new Scanner(System.in);
System.out.print("Please enter Roman Symbol:");
String s = keyboard.nextLine();
RomInt temp = new RomInt();
temp.getVal(s);
temp.assign(s);
temp.disp();
}
I am trying to write calculator for + - * / without conditions. The operator is stored as a string.
Is there anyway to achieve it?
public class Main {
/**
* #param args
*/
public static void main(String[] args) {
////String Operator = "";
String L1="";
String L2="";
String op = "+";
double a = 3;
double b = 2;
//Operator p = p.
Operator p;
b = Operator.count(a, op, b);
System.out.println(b);
}
public enum Operator {
PLUS("+"), MINUS("-"), DIVIDE("/"), MULTIPLY("*");
private final String operator;
public static double count(double a,String op,double b) {
double RetVal =0;
switch (Operator.valueOf(op)) {
case PLUS:
RetVal= a + b;
case MINUS:
RetVal= a - b;
case DIVIDE:
RetVal= a / b;
case MULTIPLY:
RetVal= a * b;
}
return RetVal;
}
Operator(String operator) {
this.operator = operator;
}
// uniwersalna stała grawitacyjna (m3 kg-1 s-2)
}
}
Got this error:
Exception in thread "main" java.lang.IllegalArgumentException: No enum const class Main$Operator.+
Any clues?
You could use a strategy pattern and store a calculation strategy for each operator.
interface Calculation {
double calculate(double op1, double op2);
}
class AddCalculation implements Calculation {
double calculate(double op1, double op2) {
return op1 + op2;
}
}
//others as well
Map<String, Calculation> m = ...;
m.put("+", new AddCalculation());
During execution you then get the calculation objects from the map and execute calculate().
i think using an enum would be a nice option:
Enum Operation{
PLUS("+")
MINUS("-")
DIVIDE("/")
MULTIPLY("*")
}
then you could go with
switch(Operation.valueOf(userInputString)){
case PLUS: return a+b;
case MINUS: return a-b;
case DIVIDE: return a/b;
case MULTIPLY: return a*b;
}
how about hashing? Hash the operators as a key-value pair ("+": +). For the string operatory, hash it and grab the value. Experiment with that
As mentioned by Peter Lawrey, ScriptEngine/JavaScript might be a good choice for this. Visit this little JavaScript interpreter applet to explore the possibilities.