i would like to include a simple RPN type calculator function in one of my projects.
basically i need a method that can convert for example:
"30 / ((1 + 4) * 3)" into "2"
does anyone know of any pre-written libs that can do this?
thanks.
You should implement Shunting Yard Algorithm
also look : Reverse Polish notation
You can use Shunting Yard (Jep API)
I suggest you to write it in python if you don't have to implement it in Java because of it's built-in methods
print eval("30 / ((1 + 4) * 3)")
ideone demo
You need a parser and a stack.
Google brought back a bunch of links. I can't recommend any of them, because none of my apps require an RPN calculator.
If this is homework, please mark it as such.
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
import java.util.Stack;
public class Rpncalculator
{
static final HashMap<String, Integer> prec;
static
{
prec = new HashMap<>();
prec.put("^", 3);
prec.put("%", 2);
prec.put("*", 2);
prec.put("/", 2);
prec.put("+", 1);
prec.put("-", 1);
}
public static void main(String[] args)
{
Queue<String> infixQueue = new LinkedList<>(); //Standard Queue class provided by Java Framework.
Scanner sc = new Scanner(System.in);
Double number = 0.0;
Character c, cNext = ' ';
String input;
String multiDigit = "";
do
{
System.out.println("Enter your INFIX expression or 'quit' to exit: ");
input = sc.nextLine();
input = input.replaceAll(" ", ""); //ignore spaces in input infix expression
if (input.equals("quit"))
{
System.exit(0);
}
for (int i = 0; i < input.length(); i++)
{
c = input.charAt(i);
if (i + 1 < input.length())
{
cNext = input.charAt(i + 1);
}
if (c.equals('(') || c.equals(')'))
{
if (c.equals('(') && cNext.equals('-'))
{
System.out.println("NEGATIVE Numbers not allowed");
main(args);
// System.exit(0);
} else
{
infixQueue.add(c.toString());
}
} else if (!Character.isDigit(c))
{
if (infixQueue.isEmpty() && c.equals('-'))
{
System.out.println("NEGATIVE Numbers not allowed");
main(args);
} else if (cNext.equals('-'))
{
System.out.println("NEGATIVE Numbers not allowed");
main(args);
} else
{
infixQueue.add(c.toString());
}
} else if (Character.isDigit(c))
{
if (i + 1 < input.length() && input.charAt(i + 1) == '.') //to handle decimal
{
int j = i + 1;
multiDigit = c.toString() + input.charAt(j); //to handle multidigit
while (j + 1 <= input.length() - 1 && Character.isDigit(input.charAt(j + 1)))
{
multiDigit = multiDigit + input.charAt(j + 1);
j++;
}
i = j;
infixQueue.add(multiDigit);
multiDigit = "";
} else if (i + 1 <= input.length() - 1 && Character.isDigit(input.charAt(i + 1)))
{
int j = i;
//multiDigit=c.toString()+input.charAt(i);
while (j <= input.length() - 1 && Character.isDigit(input.charAt(j)))
{
multiDigit = multiDigit + input.charAt(j);
j++;
}
i = j - 1;
infixQueue.add(multiDigit);
multiDigit = "";
} else
{
infixQueue.add(c.toString());
}
}
}
infixToPostfix(infixQueue);
} while (!input.equals("quit"));
}
//method to convert from infix to postfix
public static void infixToPostfix(Queue<String> infixQueue)
{
Stack operatorStack = new Stack();
Queue<String> postQueue = new LinkedList<>();
String t;
while (!infixQueue.isEmpty())
{
t = infixQueue.poll();
try
{
double num = Double.parseDouble(t);
postQueue.add(t);
} catch (NumberFormatException nfe)
{
if (operatorStack.isEmpty())
{
operatorStack.add(t);
} else if (t.equals("("))
{
operatorStack.add(t);
} else if (t.equals(")"))
{
while (!operatorStack.peek().toString().equals("("))
{
postQueue.add(operatorStack.peek().toString());
operatorStack.pop();
}
operatorStack.pop();
} else
{
while (!operatorStack.empty() && !operatorStack.peek().toString().equals("(") && prec.get(t) <= prec.get(operatorStack.peek().toString()))
{
postQueue.add(operatorStack.peek().toString());
operatorStack.pop();
}
operatorStack.push(t);
}
}
}
while (!operatorStack.empty())
{
postQueue.add(operatorStack.peek().toString());
operatorStack.pop();
}
System.out.println();
System.out.println("Your POSTFIX expression is: ");
//numbers and operators all seperated by 1 space.
for (String val : postQueue)
{
System.out.print(val + " ");
}
postfixEvaluation(postQueue);
}
//method to calculate the reuslt of postfix expression.
public static void postfixEvaluation(Queue<String> postQueue)
{
Stack<String> eval = new Stack<>(); //Standard Stack class provided by Java Framework.
String t;
Double headNumber, nextNumber, result = 0.0;
while (!postQueue.isEmpty())
{
t = postQueue.poll();
try
{
double num = Double.parseDouble(t);
eval.add(t);
} catch (NumberFormatException nfe)
{
headNumber = Double.parseDouble(eval.peek());
eval.pop();
nextNumber = Double.parseDouble(eval.peek());
eval.pop();
switch (t)
{
case "+":
result = nextNumber + headNumber;
break;
case "-":
result = nextNumber - headNumber;
break;
case "*":
result = nextNumber * headNumber;
break;
case "/":
//in java, there is no exception generated when divided by zero and thus checking
//for
if (headNumber == 0)
{
System.out.println("\nERROR: Cannot Divide by zero!\n");
return;
} else
{
result = nextNumber / headNumber;
break;
}
case "%":
result = nextNumber % headNumber;
break;
case "^":
result = Math.pow(nextNumber, headNumber);
break;
}
eval.push(result.toString());
}
}
System.out.println("\nRESULT is: ");
DecimalFormat df = new DecimalFormat("0.000");
for (String val : eval)
{
System.out.println(df.format(Double.parseDouble(val)) + "\n");
}
}
}
Actually, this is not an "RPN" question, because you want to evaluate an algebraic expression.
7th is primarily a RPN language, but can evaluate algebraic expressions with the restriction that they must not contain spaces and must be enclosed in round braces:
private static final ScriptEngineManager mgr = new ScriptEngineManager();
private static final ScriptEngine engine = mgr.getEngineByName( "7th" );
…
try {
Number d;
d = (Number)engine.eval( "(30/((1+4)*3))" ); // 2.0
d = (Number)engine.eval( "30 1 4 + 3 * /" ); // 2.0
}
catch( ScriptException ex ) {
ex.printStackTrace();
}
Related
I want to write a program to calculate output given arithmetical expression . Like that:
My input is: * + * + 1 2 + 3 4 5 6
My output should be: 156
I wrote a Java program to do this using Stack data type.
Here is my Java program:
import java.util.Scanner;
import java.util.Stack;
public class Main {
public static void main(String args[]){
Stack stack =new Stack();
String input;
String trimmedInput[];
int output;
int number1,number2;
int countOfNumber,j;
Scanner scanner = new Scanner(System.in);
System.out.println("put your arithmetical expression. Using Space between ");
input=scanner.nextLine();
trimmedInput=input.split("\\s+");
// for(String a:trimmedInput)
// System.out.println(a);
countOfNumber=trimmedInput.length;
for(j=0;j<countOfNumber;j++) {
if (isNumeric(trimmedInput[j])) {
stack.push(trimmedInput[j]);
}
if (trimmedInput[j].equals("+")) {
number1 = Integer.parseInt((String) stack.pop()) ;
number2 = Integer.parseInt((String) stack.pop()) ;
output = number1 + number2;
stack.push(output);
}
if(trimmedInput[j].equals("-")){
number1 = Integer.parseInt((String) stack.pop()) ;
number2 = Integer.parseInt((String) stack.pop()) ;
output = number1-number2;
stack.push(output);
}
if(trimmedInput[j].equals("*")){
number1 = Integer.parseInt((String) stack.pop()) ;
number2 = Integer.parseInt((String) stack.pop()) ;
output = number1*number2;
stack.push(output);
}
if(trimmedInput[j].equals("/")){
number1 = Integer.parseInt((String) stack.pop()) ;
number2 = Integer.parseInt((String) stack.pop()) ;
output = number1/number2;
stack.push(output);
}
}
while(!stack.isEmpty())
System.out.println(stack.pop());
}
public static boolean isNumeric(String str)
{
try
{
double d = Double.parseDouble(str);
}
catch(NumberFormatException nfe)
{
return false;
}
return true;
}
}
Ok. Here is my problem. If I want to calculate * + * + 1 2 + 3 4 5 6 something like that, my compiler gives an error like that:
Exception in thread "main" java.util.EmptyStackException
at java.util.Stack.peek(Stack.java:102)
at java.util.Stack.pop(Stack.java:84)
at Main.main(Main.java:41)
Here is my 41. row at code:
number1 = Integer.parseInt((String) stack.pop()) ;
I cannot figured out what is problem in my code. I'm new at Java. Please help me. Thanks a lot :)
Your code is giving you error because you are parsing from left-to-right. So the first string it gets is "*" - star. So, it checks that it's a star, and pops from the stack. But, the stack is empty!! So, you should traverse from right-to-left and when you find number push into stack, and when you find an operator, do the operation
for (int i = trimmedInput.length-1; i >= 0; i--) {
if (isNumeric(trimmedInput[i])) stack.push(trimmedInput[i]);
else if (trimmedInput[i].equals("*")) {
// here you might get StackEmptyException if your expression is invalid
// if you want to avoid that, then use try-catch and throw your custom InvalidExpressionExceptiono
number1 = Integer.parseInt((String)stack.pop());
number2 = Integer.parseInt((String)stack.pop());
output = number1*number2;
stack.push(output);
}
.
.
. // do the same for other operators
.
.
}
Updated answer
Shouldn't you push all operators into the stack, and pop it out after you see two operands ? (You will have two operands when one is at the top of the stack, and the other just comes in i.e. trimmedInput[j]).
Alternative solution for above problem ..
import java.util.Scanner;
import java.util.Stack;
public class Expression
{
static int i = 0 ;
static Stack stack = new Stack<>();
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String input = in.next();
input += in.nextLine();
char expr[] = input.toCharArray();
for(int j = expr.length-1 ; j>=0 ; j--)
{
stack.push(process(expr[j]));
}
System.out.println("Result is : " + stack.pop());
}
public static int process(char val)
{
int res = val;
int flag = 0;
if(val == '+')
{
flag = 1 ;
res = (Integer)stack.pop() + (Integer)stack.pop();
}
else if(val == '-')
{
flag =1 ;
res = (Integer)stack.pop() - (Integer)stack.pop();
}
else if(val == '*')
{
flag =1 ;
res = (Integer)stack.pop() * (Integer)stack.pop();
}
else if(val == '/')
{
flag =1 ;
res = ((Integer)stack.pop() / (Integer)stack.pop());
}
if(flag == 1)
return res;
else
return res-48;
}
public static void print()
{
int k = i;
while(--k >= 0)
{
System.out.print(stack.peek() + " : ");
}
System.out.println("\n");
}
}
import java.util.*;
public class HangManP5
{
public static void main(String[] args)
{
int attempts = 10;
int wordLength;
boolean solved;
Scanner k = new Scanner(System.in);
System.out.println("Hey, what's your name?");
String name = k.nextLine();
System.out.println(name+ ", hey! This is a hangman game!\n");
RandomWord(word);
int len = word.length();
char[] temp = new char[len];
for(int i = 0; i < temp.length; i++)
{
temp[i] = '*';
}
System.out.print("\n");
System.out.print("Word to date: ");
while (attempts <= 10 && attempts > 0)
{
System.out.println("\nAttempts left: " + attempts);
System.out.print("Enter letter: ");
String test = k.next();
if(test.length() != 1)
{
System.out.println("Please enter 1 character");
continue;
}
char testChar = test.charAt(0);
int foundPos = -2;
int foundCount = 0;
while((foundPos = word.indexOf(testChar, foundPos + 1)) != -1)
{
temp[foundPos] = testChar;
foundCount++;
len--;
}
if(foundCount == 0)
{
System.out.println("Sorry, didn't find any matches for " + test);
}
else
{
System.out.println("Found " + foundCount + " matches for " + test);
}
for(int i = 0; i < temp.length; i++)
{
System.out.print(temp[i]);
}
System.out.println();
if(len == 0)
{
break; //Solved!
}
attempts--;
}
if(len == 0)
{
System.out.println("\n---------------------------");
System.out.println("Solved!");
}
else
{
System.out.println("\n---------------------------");
System.out.println("Sorry you didn't find the mystery word!");
System.out.println("It was \"" + word + "\"");
}
}
public static String RandomWord(String word)
{
//List of words
Random r = new Random();
int a = 1 + r.nextInt(5);
if(a == 1)
{
word=("Peace");
}
if(a == 2)
{
word=("Nuts");
}
if(a == 3)
{
word=("Cool");
}
if(a == 4)
{
word=("Fizz");
}
if(a == 5)
{
word=("Awesome");
}
return (word);
}
}
Ok, so this is my code for a hangman game, the only thing I have left to do is to get my program to randomize one of the words, which it should do in the method successfully. But the only problem I'm having is getting the String variable "word" to go back to the main class (there are errors underlining all the "word" variables in the main class).
If I could get help with either this or another way to produce a random word from a list, that would be amazing.
In java, parameters are passed by value and not by reference. Therefore, you cannot change the reference of a parameter.
In your case, you need to do:
public static String getRandomWord() {
switch(new Random().nextInt(5)) {
case 0:
return "Peace";
case 1:
return "Nuts";
// ...
default:
throw new IllegalStateException("Something went wrong!");
}
}
And in main:
// ...
String word = getRandomWord();
int len = word.length();
// ...
You can't modify the caller's reference.
RandomWord(word);
needs to be something like
word = RandomWord(word);
Also, by convention, Java methods start with a lower case letter. And, you could return the word without passing one in as an argument and I suggest you save your Random reference and use an array like
private static Random rand = new Random();
public static String randomWord() {
String[] words = { "Peace", "Nuts", "Cool", "Fizz", "Awesome" };
return words[rand.nextInt(words.length)];
}
And then call it like
word = randomWord();
I'm doing an assignment where the goal is to, among other things, to add two large integers. Here is my code, spread out into four files.
Main that we cannot change:
import java.util.*;
import MyUtils.MyUtil;
public class CSCD210HW7
{
public static void main(String [] args)throws Exception
{
int choice;
String num;
LargeInt one, two, three = null;
Scanner kb = new Scanner(System.in);
num = HW7Methods.readNum(kb);
one = new LargeInt(num);
num = HW7Methods.readNum(kb);
two = new LargeInt(num);
do
{
choice = MyUtil.menu(kb);
switch(choice)
{
case 1: System.out.println(one + "\n");
break;
case 2: System.out.println("The value of the LargeInt is: " + two.getValue() + "\n");
break;
case 3: num = HW7Methods.readNum(kb);
one.setValue(num);
break;
case 4: if(one.equals(two))
System.out.println("The LargeInts are equal");
else
System.out.println("The LargeInts are NOT equal");
break;
case 5: three = two.add(one);
System.out.printf("The results of %s added to %s is %s\n", one.getValue(), two.getValue(), three.getValue());
break;
case 6: HW7Methods.displayAscendingOrder(one, two, three);
break;
default: if(two.compareTo(one) < 0)
System.out.printf("LargeInt %s is less than LargeInt %s\n", two.getValue(), one.getValue());
else if(two.compareTo(one) > 0)
System.out.printf("LargeInt %s is greater than LargeInt %s\n", two.getValue(), one.getValue());
else
System.out.printf("LargeInt %s is equal to LargeInt %s\n", two.getValue(), one.getValue());
break;
}// end switch
}while(choice != 8);
}// end main
}// end class
LargeInt Class(Custom Class We Created)
public class LargeInt implements Comparable<LargeInt>
{
private int[]myArray;
private LargeInt()
{
this("0");
}
public LargeInt(final String str)
{
this.myArray = new int[str.length()];
for(int x = 0; x < this.myArray.length; x++)
{
this.myArray[x] = Integer.parseInt(str.charAt(x)+ "");
}
}
public LargeInt add(final LargeInt passedIn)
{
String stringOne = myArray.toString();
String stringTwo = passedIn.myArray.toString();
int r = Integer.parseInt(stringOne);
int e = Integer.parseInt(stringTwo);
int s = r + e;
return new LargeInt(""+s);
}
public void setValue(final String arrayString)
{
this.myArray = new int[arrayString.length()];
for(int x = 0; x < myArray.length; x++)
{
this.myArray[x]=arrayString.charAt(x);
}
}
#Override
public int compareTo(LargeInt passedIn)
{
if(passedIn == null)
{
throw new RuntimeException("NullExceptionError");
}
int ewu = 0;
int avs = 0;
if(this.myArray.length != passedIn.myArray.length)
{
return this.myArray.length - passedIn.myArray.length;
}
for(int i = 0; i < this.myArray.length -1; i++)
{
if(this.myArray[i] != passedIn.myArray[i])
{
return this.myArray[i]-passedIn.myArray[i];
}
}
return ewu-avs;
}
public int hashCode()
{
String p = "";
for(int f = 0; f < this.myArray.length; f++)
{
p += myArray[f];
}
return p.hashCode();
}
public String getValue()
{
String h = "";
for(int t = 0; t < this.myArray.length; t++)
{
h += myArray[t];
}
return h;
}
#Override
public boolean equals(Object jbo)
{
if(jbo == null)
{
return false;
}
if(!(jbo instanceof LargeInt))
{
return false;
}
LargeInt k =(LargeInt)jbo;
if(k.myArray.length != this.myArray.length)
{
return false;
}
for(int d = 0; d < this.myArray.length; d++)
{
if(k.myArray[d] != myArray[d])
{
return false;
}
}
return true;
}
#Override
public String toString()
{
String c = "";
for(int q = 0; q < this.myArray.length; q++)
{
c += myArray[q];
}
return "The LargeInt is: " + c;
}
}
HW7Methods File
import java.util.*;
import java.io.*;
public class HW7Methods
{
public static String readNum(Scanner kb)
{
String num = "";
System.out.print("Enter Your Large Int: ");
num = kb.nextLine();
return num;
}
public static void displayAscendingOrder(final LargeInt first, final LargeInt second, final LargeInt third)
{
String highestInt;
if(first.compareTo(second) >= 0 && first.compareTo(third) >= 0)
{
highestInt = first.getValue();
}
else if(second.compareTo(first) >= 0 && second.compareTo(third) >= 0)
{
highestInt = second.getValue();
}
else
{
highestInt = third.getValue();
}
String middleInt;
if(first.compareTo(second) >= 0 && first.compareTo(third) <= 0)
{
middleInt = first.getValue();
}
else if(second.compareTo(first) >= 0 && second.compareTo(third) <= 0)
{
middleInt = second.getValue();
}
else
{
middleInt = third.getValue();
}
String lowestInt;
if(first.compareTo(second) <= 0 && first.compareTo(third) <= 0)
{
lowestInt = first.getValue();
}
else if(second.compareTo(first) <= 0 && second.compareTo(third) <= 0)
{
lowestInt = second.getValue();
}
else
{
lowestInt = third.getValue();
}
System.out.println("The LargeInts in order are: " + lowestInt + ", " + middleInt + ", " + highestInt);
}
}
MyUtil file
package MyUtils;
import java.io.*;
import java.util.Scanner;
public class MyUtil
{
public static int menu(Scanner kb)
{
int userChoice;
System.out.println("1) Print First Int");
System.out.println("2) Print Second Int");
System.out.println("3) Add Different Int");
System.out.println("4) Check If Equal");
System.out.println("5) Add Large Ints");
System.out.println("6) Display In Ascending Order");
System.out.println("7) Compare Ints");
System.out.println("8) Quit");
kb = new Scanner(System.in);
System.out.print("Please Select Your Choice: ");
userChoice = kb.nextInt();
while(userChoice < 1 || userChoice > 8)
{
System.out.print("Invalid Menu Choice. Please Re-Enter: ");
userChoice = kb.nextInt();
}
return userChoice;
}
}
When I go to run this code, it prompts me for two Large Integers like it's supposed to. However, when I choose option 5 to add them, this is what I get:
Exception in thread "main" java.lang.NumberFormatException: For input string: "[I#55f96302"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:580)
at java.lang.Integer.parseInt(Integer.java:615)
at LargeInt.add(LargeInt.java:24)
at CSCD210HW7.main(CSCD210HW7.java:41)
I've never seen that type of error before. Can someone tell me what is going on?
For input string: "[I#55f96302
That is not a "proper" String you are trying to parse here.
This is what an int[] looks like when you call toString() on it.
String stringOne = myArray.toString();
Why do you do that? What is that supposed to do?
int r = Integer.parseInt(stringOne);
int e = Integer.parseInt(stringTwo);
int s = r + e;
From the looks of it, you try to handle "large" ints with your LargeInt class by somehow storing them in an array of ints. That's okay, BigInteger also works like that (more or less), but you cannot just do calculations by trying to convert back to int (after all those numbers are too big for int arithmetic to handle, even if you do the string parsing properly).
I'm trying to make a simple calculator in Java which takes input in the form of a string and does a simple '+' and '-' operation.
Single digit inputs work but my problem is when i try to implement this for double digit
input string is: 5+20+5+11
list 1 = [5, 20, 2, 0, 5, 11, 1]
list 2 = [+, +, +]
Answer:27
I need to find a way where after storing [5] in list1 how i can add [5,20] instead of [5,20,2,0] which the current code is doing.
public int calC(String input) {
int len = input.length();
ArrayList list1 = new ArrayList();
ArrayList list2 = new ArrayList();
for (int i = 0; i < len; i++) {
if ((input.charAt(i) != '+') && (input.charAt(i) != '-')) {
// check if the number is double-digit
if ((i + 1 <= len - 1)) {
if ((input.charAt(i + 1) != '+')&& (input.charAt(i + 1) != '-')) {
String temp = "";
temp = temp + input.charAt(i) + input.charAt(i + 1);
int tempToInt = Integer.parseInt(temp);
// adding the double digit number
list1.add(tempToInt);
}
// add single digit number
list1.add(input.charAt(i) - '0');
}
} else {
// adding the symbols
list2.add(input.charAt(i));
}
}
int result = 0;
result = result + (int) list1.get(0);
for (int t = 0; t < list2.size(); t++) {
char oper = (char) list2.get(t);
if (oper == '+') {
result = result + (int) list1.get(t + 1);
} else if (oper == '-') {
result = result - (int) list1.get(t + 1);
}
}
return result;
}
Edit: working version
#Ker p pag thanks for the updated methods
input string is: 5+20+5+11
[5, 20, 5, 11]
[+, +, +]
Answer:41
I'll need to try to implement this with stack as suggested but the current version works
static boolean isDigit(char check) {
if (Character.isDigit(check)) {
return true;
}
return false;
}
public static int calC(String input) {
int len = input.length();
ArrayList list1 = new ArrayList();
ArrayList list2 = new ArrayList();
for (int i = 0; i < len; i++) {
if ((i + 1 <= len - 1)) {
if (isDigit(input.charAt(i)) && isDigit(input.charAt(i + 1))) {
String temp = input.charAt(i) + "" + input.charAt(i + 1);
int toInt = Integer.parseInt(temp);
list1.add(toInt);
i = i+1;
} else if (isDigit(input.charAt(i))) {
list1.add(input.charAt(i)- '0');
} else {
list2.add(input.charAt(i));
}
}
}
int result = 0;
result = result + (int) list1.get(0);
for (int t = 0; t < list2.size(); t++) {
char oper = (char) list2.get(t);
if (oper == '+') {
result = result + (int) list1.get(t + 1);
} else if (oper == '-') {
result = result - (int) list1.get(t + 1);
}
}
return result;
}
Here is the code:
String a = "5+20-15+8";
System.out.println(a);
String operators[]=a.split("[0-9]+");
String operands[]=a.split("[+-]");
int agregate = Integer.parseInt(operands[0]);
for(int i=1;i<operands.length;i++){
if(operators[i].equals("+"))
agregate += Integer.parseInt(operands[i]);
else
agregate -= Integer.parseInt(operands[i]);
}
System.out.println(agregate);
If you want the result 41 for input string "5+20+5+11",
why not use ScriptEngineManager with JavaScript engine,
public double calC(String input) {
int result = 0;
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("JavaScript");
return (Double)engine.eval(input);
}
But note that the return type is double here.
If you want only int as return type in this case, try with this
return new BigDecimal(engine.eval(input).toString()).intValue();
Another way to think about this:
public class InlineParsing {
public static void main(String []args){
String input = "5-2+20+5+11-10";
input = input.replace(" ","");
String parsedInteger = "";
String operator = "";
int aggregate = 0;
for (int i = 0; i < input.length(); i++){
char c = input.charAt(i);
if (Character.isDigit(c)) {
parsedInteger += c;
}
if (!Character.isDigit(c) || i == input.length()-1){
int parsed = Integer.parseInt(parsedInteger);
if (operator == "") {
aggregate = parsed;
}
else {
if (operator.equals("+")) {
aggregate += parsed;
}else if (operator.equals("-")){
aggregate -= parsed;
}
}
parsedInteger ="";
operator = ""+c;
}
}
System.out.println("Sum of " + input+":\r\n" + aggregate);
}
}
It's basically a state machine that traverses over each char.
Iterate over each char:
if current char is a digit, add to current number buffer
if current char is not a digit or we're parsing the last digit
if an operator has been parsed use that to add the newly parsed number to the sum
if no operator has been parsed, set sum to current parsed number
clear current number buffer
store current char as operator
I agree that stack is the best solution,but still giving an alternative way
of doing this.
String input = "5+20+11+1";
StringBuilder sb = new StringBuilder();
List<Integer> list1 = new ArrayList<Integer>();
List<Character> list2 = new ArrayList<Character>();
char[] ch = input.toCharArray();
for(int i=0;i<ch.length;i++)
{
if(ch[i]!='+')
{
sb.append(ch[i]);
}else
{
list2.add(ch[i]);
list1.add(Integer.valueOf(sb.toString()));
sb.setLength(0);
}
}
if(sb.length()!=0)
list1.add(Integer.valueOf(sb.toString()));
System.out.println(list1.size());
for(Integer i:list1)
{
System.out.println("values"+i);
}
for storing the input to the list you could try this snippet
for (int i = 0; i < input.length() - 1; i++) {
// make a method
// check if current character is number || check if current
// character is number and the next character
if (isDigit(input.charAt(i)) && isDigit(input.charAt(i + 1))) {
list.add(input.charAt(i) +""+ input.charAt(i + 1));
} else if (isDigit(input.charAt(i))) {
list.add(input.charAt(i));
}else{
operator.add(input.charAt(i));
}
}
//check if it is a number
public boolean isDigit(char input){
if(input == '1' ||
input == '2' ||
input == '3' ||
input == '4' ||
input == '5' ||
input == '6' ||
input == '7' ||
input == '8' ||
input == '9' ||
input == '0')
return true;
return false;
}
I could advise you to use Exp4j. It is easy to understand as you can see from the following example code:
Expression e = new ExpressionBuilder("3 * sin(y) - 2 / (x - 2)")
.variables("x", "y")
.build()
.setVariable("x", 2.3)
.setVariable("y", 3.14);
double result = e.evaluate();
Especially for the case of using more complex expression this could be a better choice.
private static int myCal() {
String[] digits = {
"1",
"2",
"3",
"4",
"5"
};
String[] ops = {
"+",
"+",
"+",
"-"
};
int temp = 0;
int res = 0;
int count = ops.length;
for (int i = 0; i < digits.length; i++) {
res = Integer.parseInt(digits[i]);
if (i != 0 && count != 0) {
count--;
switch (ops[i - 1]) {
case "+":
temp = Math.addExact(temp, res);
break;
case "-":
temp = Math.subtractExact(temp, res);
break;
case "*":
temp = Math.multiplyExact(temp, res);
break;
case "/":
temp = Math.floorDiv(temp, res);
break;
}
}
}
return temp;
}
You can check this code that I created using array only. I also tried several arithmetic problems also your given problem.
Please see also the comments within the method.
public static String Calculator(String str) {
// will get all numbers and store it to `numberStr`
String numberStr[] = str.replaceAll("[+*/()-]+"," ").split(" ");
// will get all operators and store it to `operatorStr`
String operatorStr[] = str.replaceAll("[0-9()]+","").split("");
int total = Integer.parseInt(numberStr[0]);
for (int i=0; i<operatorStr.length; i++) {
switch (operatorStr[i]) {
case "+" :
total += Integer.parseInt(numberStr[i+1]);
break;
case "-" :
total -= Integer.parseInt(numberStr[i+1]);
break;
case "*" :
total *= Integer.parseInt(numberStr[i+1]);
break;
case "/" :
total /= Integer.parseInt(numberStr[i+1]);
break;
}
if(i+2 >= operatorStr.length) continue; // if meets the last operands already
numberStr[i+1] = String.valueOf(total);
}
return String.valueOf(total);
}
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
ArrayList<Character> listOfOpertionsCharFORM = new ArrayList<>();
ArrayList<Character> listOfNumbersCharFORM = new ArrayList<>();
ArrayList<Integer> listOfNumbersINTEGERFORM = new ArrayList<>();
int Total = 0;
Scanner sc = new Scanner(System.in);
String input;
System.out.print("Please enter your math equation :");
input = sc.nextLine();
System.out.println("string is : " + input);
separator();
char[] convertAllToChar = input.toCharArray();
for (char inputToChar : convertAllToChar) {
System.out.println("convertAllToChar " + inputToChar);
}
for (int i = 0; i < input.length(); i++) {
if (convertAllToChar[i] == '+') {
listOfOpertionsCharFORM.add(convertAllToChar[i]);
}
if (convertAllToChar[i] == '-') {
listOfOpertionsCharFORM.add(convertAllToChar[i]);
}
if (convertAllToChar[i] == '*') {
listOfOpertionsCharFORM.add(convertAllToChar[i]);
}
if (convertAllToChar[i] == '/') {
listOfOpertionsCharFORM.add(convertAllToChar[i]);
}
if (Character.isDigit(convertAllToChar[i])) {
listOfNumbersCharFORM.add(convertAllToChar[i]);
}
}
separator();
for (Character aa : listOfOpertionsCharFORM) {
System.out.println("list Of Operations Char FORM " + aa);
}
separator();
for (Character aa : listOfNumbersCharFORM) {
System.out.println("list Of Numbers Char FORM " + aa);
}
separator();
for (Character aa : listOfNumbersCharFORM) {
if (aa == '0') listOfNumbersINTEGERFORM.add(0);
if (aa == '1') listOfNumbersINTEGERFORM.add(1);
if (aa == '2') listOfNumbersINTEGERFORM.add(2);
if (aa == '3') listOfNumbersINTEGERFORM.add(3);
if (aa == '4') listOfNumbersINTEGERFORM.add(4);
if (aa == '5') listOfNumbersINTEGERFORM.add(5);
if (aa == '6') listOfNumbersINTEGERFORM.add(6);
if (aa == '7') listOfNumbersINTEGERFORM.add(7);
if (aa == '8') listOfNumbersINTEGERFORM.add(8);
if (aa == '9') listOfNumbersINTEGERFORM.add(9);
}
for (Integer aaa : listOfNumbersINTEGERFORM) {
System.out.println("list Of Numbers INTEGER FORM " + aaa);
}
separator();
separator();
separator();
System.out.print(listOfNumbersINTEGERFORM);
System.out.print(listOfOpertionsCharFORM);
System.out.println();
System.out.println();
if (listOfNumbersINTEGERFORM.size() == (listOfOpertionsCharFORM.size() + 1)) {
for (int i = 0; i < listOfOpertionsCharFORM.size(); i++) {
System.out.println("i :" + i);
if (listOfOpertionsCharFORM.get(i) == '+') if (i == 0) {
Total = Total + listOfNumbersINTEGERFORM.get(i) + listOfNumbersINTEGERFORM.get(i + 1);
System.out.println("total : " + Total);
separatorShort();
} else {
Total = Total + listOfNumbersINTEGERFORM.get(i + 1);
System.out.println("total : " + Total);
separatorShort();
}
if (listOfOpertionsCharFORM.get(i) == '-') if (i == 0) {
Total = Total + listOfNumbersINTEGERFORM.get(i) - listOfNumbersINTEGERFORM.get(i + 1);
System.out.println("total : " + Total);
separatorShort();
} else {
Total = Total - listOfNumbersINTEGERFORM.get(i + 1);
System.out.println("total : " + Total);
separatorShort();
}
if (listOfOpertionsCharFORM.get(i) == '*') if (i == 0) {
Total = Total + listOfNumbersINTEGERFORM.get(i) * listOfNumbersINTEGERFORM.get(i + 1);
System.out.println("total : " + Total);
separatorShort();
} else {
Total = Total * listOfNumbersINTEGERFORM.get(i + 1);
System.out.println("total : " + Total);
separatorShort();
}
if (listOfOpertionsCharFORM.get(i) == '/') if (i == 0) {
Total = Total + listOfNumbersINTEGERFORM.get(i) / listOfNumbersINTEGERFORM.get(i + 1);
System.out.println("total : " + Total);
separatorShort();
} else {
Total = Total / listOfNumbersINTEGERFORM.get(i + 1);
System.out.println("total : " + Total);
separatorShort();
}
}
} else {
System.out.println("*********###############**********");
System.out.println("** your input not correct input **");
System.out.println("*********###############**********");
}
System.out.println("*** Final Answer *** : " + Total);
}
public static void separator() {
System.out.println("___________________________________");
}
public static void separatorShort() {
System.out.println("_____________");
}
import java.util.Scanner;
public class Improved {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Enter a number operaion number: ");
int operand1 = Integer.parseInt(input.nextLine());
char expo1 = input.next().charAt(0);
int operand2 = Integer.parseInt(input.nextLine());
System.out.println( operand1 + expo1 + operand2 + "=");
if ( expo1 == '/' && operand2 == '0' ){
System.out.println("Cannot divide by zero"); }
else
if (expo1 == '-') {
System.out.println(operand1-operand2);
} else
if (expo1 == '+') {
System.out.println(operand1+operand2);
} else
if (expo1 == '/') {
System.out.println(operand1/operand2);
} else
if (expo1 == '%') {
System.out.println(operand1%operand2);
}
else{
System.out.println(" Error.Invalid operator.");
}
}
}
//This bottom works, but I found out that this is not what is supposed to be done with this problem
/*
public class Else {
public static void main(String[] args) {
int operand1;
char exp1;
int operand2;
if (args.length != 3 ) {
System.err.println("*** Program needs 3 arguements***");
System.err.println("Usage: java Else int1 exp int2");
System.exit(1);
}
operand1 = Integer.parseInt(args[0]);
exp1 = args[1].charAt(0);
operand2 = Integer.parseInt(args[2]);
System.out.print(args[0] + args[1] + args[2] + "=");
if(exp1 == '-') {
System.out.println(operand1 - operand2);
} else
if (exp1 == '+') {
System.out.println(operand1 + operand2);
} else
if (exp1 == '/') {
System.out.println(operand1 / operand2);
} else
if (exp1 == '%') {
System.out.println(operand1 % operand2);
}
else{
System.out.println(" Error.Invalid operator.");
}
}
}
*/
What I want the program to do is ask one to enter a math operation 1/2 or 1%2 (not multiplication)
, but just like that without spaces. Still, I want to check which operation is being done which is why i put the if statements. What I don't get is how the program would know when an operation appears in a string. I'm not even sure if I set it correctly. Overall, I want a string that reads the number then the operation an then the number again. I'm sorry if this seems like doing my hw, but I have tried making this program multiple times, but can't understand how I can do this with a string. I wrote the second one to show that I have done this multiple times, so you can ignore it. Thank You very much!
read input as a String using:
String inputString = input.nextLine();
get the index of the operator:
int indexOp = inputString.indexOf("+");
if(indexOp < 0) indexOp = inputString.indexOf("-"); //cannot find +, so find -
if(indexOp < 0) indexOp = inputString.indexOf("/"); //cannot find -, so find /
if(indexOp < 0) indexOp = inputString.indexOf("%"); //cannot find /, so find %
get the first and second operand with:
int operand1 = Integer.parseInt(inputString.substring(0,indexOp));
int operand2 = Integer.parseInt(inputString.substring(indexOp+1,inputString.length());
get the operator from the indexOp we got earlier:
char operator = inputString.charAt(indexOp);
Hope it helps :)
I have no doubt there are a number of ways this might be achieved, this is simply another example...
What this tries to do, is break down the incoming text into groups of digits and non digits. It then loops through these groups making up the various elements of the calculation...
Scanner input = new Scanner(System.in);
System.out.println("Enter a number operaion number: ");
String text = input.nextLine();
System.out.println("Input = " + text);
text = text.replaceAll("\\s", "");
System.out.println("Parse = " + text);
Pattern p = Pattern.compile("\\d+|\\D+");
Matcher m = p.matcher(text);
int index = 0;
int op1 = -1;
int op2 = -2;
String exp1 = "";
while (index < 3 && m.find()) {
System.out.println(index);
String part = m.group();
switch (index) {
case 0:
op1 = Integer.parseInt(part);
break;
case 2:
op2 = Integer.parseInt(part);
break;
case 1:
exp1 = part;
break;
}
index++;
}
System.out.println(op1 + " " + exp1 + " " + op2);
What this does have, is the power to to allow you to supply a much longer calculation, for example 20+30/40-50...etc.
You would need to park each operand and exponent into some kind of List and extract them as you need them...or you could actually do the calculation directly within the while loop
Try this:
package week11;
import java.util.Scanner;
public class maths {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("enter a number ");
int x = scanner.nextInt();
System.out.println("put +, -, / or * ");
char expo1 = scanner.next().charAt(0);
System.out.println("second number please ");
int y = scanner.nextInt();
System.out.println( "Answer is" + ":");
if ( expo1 == '/' && y == '0' ){
System.out.println("cannot be divided by 0"); }
else
if (expo1 == '-') {
System.out.println(x-y);
} else
if (expo1 == '+') {
System.out.println(x+y);
} else
if (expo1 == '/') {
System.out.println(x/y);
} else
if (expo1 == '%') {
System.out.println(x%y);
}
else{
System.out.println(" Error!");
}
}
}
I would like to add another solution, which removes a lot of the parsing work.
import java.util.Scanner;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
class Scratch {
public static void main(String[] args) throws ScriptException {
System.out.println("Enter an operation:");
Scanner input = new Scanner(System.in);
String operation = input.nextLine();
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("js");
Object result = engine.eval(operation);
System.out.printf("%s = %s%n", operation, result);
}
}
sample result
Enter an operation:
2 + 3 * 4
2 + 3 * 4 = 14.0