Java String Calculator - java

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("_____________");
}

Related

Java booth algorithm Shift or addition trouble

I just need a little help programming booths algorithm into java, I'm really not sure how to fix somethings, right now adding the right shift makes the entire answer 1(will show a few examples of inputs and outputs to explain and show) I know its converting to binary properly so I think my problem is in my shift and adding function.
public static void main(String args[]){
Scanner sc = new Scanner(System.in);
System.out.print("Enter the first number: ");
int operand1 = sc.nextInt();
System.out.print("Enter the second number: ");
int operand2 = sc.nextInt();
String answer = multiply(operand1, operand2);
System.out.println(answer);
}
static String appendZeros(int n){
String result = "";
for(int i = 0; i < n; i++) result += "0";
return result;
}
public static String toBinary(int x, int len)
{
if (len > 0)
{
return String.format("%" + len + "s",
Integer.toBinaryString(x)).replaceAll(" ", "0");
}
return null;
}
static String add(String a, String b){
String result = "";
char carry = '0';
for(int i = a.length()-1; i >= 0; i--){
String condition = "" + a.charAt(i) + b.charAt(i) + carry;
switch(condition){
case "000": result = "0" + result; break;
case "001": result = "1" + result; carry = '0'; break;
case "010": result = "1" + result; break;
case "011": result = "0" + result; break;
case "100": result = "1" + result; break;
case "101": result = "0" + result; break;
case "110": result = "0" + result; carry = '1'; break;
case "111": result = "1" + result; break;
}
}
return result;
}
static String rightShift(String str){
String result = "";
for(int i = 0; i < str.length(); i++){
if(i == 0) result += str.charAt(i);
else result += str.charAt(i-1);
}
return result;
}
static String multiply(int a, int b){
String op1 = toBinary(a, 8);
String op2 = toBinary(b, 8);
String negop2 = toBinary(-b, 8);
if (op1.length() > 8)
{
op1 = op1.substring(op1.length() - 8);
}
if (op2.length() > 8)
{
op2 = op2.substring(op2.length() - 8);
}
if (negop2.length() > 8)
{
negop2 = negop2.substring(negop2.length() - 8);
}
System.out.println(op1 + " " + op2 + " " + negop2);
char prev = '0';
String product = appendZeros(16-op1.length())+op1;
for(int i = 0; i < 8; i++){
if(i > 0) prev = product.charAt(15);
if(product.charAt(15)=='0' && prev == '1'){
String temp = appendZeros(8-op2.length()) + op2 + appendZeros(8);
product = add(product, temp);
}
if(product.charAt(15)=='1' && prev == '0'){
String temp = appendZeros(8-negop2.length()) + negop2 + appendZeros(8);
product = add(product, temp);
}
product=rightShift(product);
}
return product;
}
input 9 1 output 1111111111111111 expected 0000000000001001 input 9 9
output 1111111111110111 expected 0000000001010001
I figured out my problem, the prev variable was being called too late so it didn't update the function properly, the prev value needed to be updated before the shift occurred. I moved it to right before the shift function was called and removed the if statement and it fixed it, it works perfectly now.
for(int i = 0; i < 8; i++){
//System.out.println("Did it change back?" + product.charAt(15) + prev);
//System.out.println("i = " + i);
if(product.charAt(15)=='0' && prev == '1'){
String temp = appendZeros(8-op2.length()) + op2 + appendZeros(8);
System.out.println(temp);
product = add(product, temp);
System.out.println("Add " + product);
}
if(product.charAt(15)=='1' && prev == '0'){
String temp = appendZeros(8-negop2.length()) + negop2 + appendZeros(8);
System.out.println(temp);
product = add(product, temp);
System.out.println("Subtract " + product);
}
prev = product.charAt(15);
product=rightShift(product);
System.out.println("Shift " + product);

Is there a reason why I cannot return inside of a While loop?

I am working on a method in my program which has to return the value purchaseMethod. The while loop needs to run until "Q" is input into the console. The issue I am having is that I cannot return while in a while loop. Is there any way around this? Possibly making an array or for loop? If the return statement is necessary to be outside of the while-loop, how would I keep the values to total for the purchaseAmount.
public static int getShoppingList(){
Scanner input = new Scanner(System.in);
int eight = 8;
int hat = 32;
int patch = 2;
int sword = 20;
int map = 100;
int shirt = 150;
int quanEight = 0;
int quanHat = 0;
int quanPatch = 0;
int quanSword = 0;
int quanMap = 0;
int quanShirt = 0;
int count = 0;
System.out.println("Enter Item Code, ? or Q: ");
String code = input.next();
// Convert input into character
char ch = code.charAt(0);
// Convert string into uppercase
ch = Character.toUpperCase(ch);
// Calculate total
while (count != 0){
int purchaseAmount = ( quanEight * eight) + ( quanHat * hat) + ( quanPatch * patch) + ( quanSword * sword) + ( quanShirt * shirt) + ( quanMap * map);
if (ch == '?'){
System.out.println("Valid Item codes are: 8 I H M S T.");
System.out.println("Q to quit.");
}
else if (ch == '8'){
quanEight ++;
}
else if (ch == 'I'){
quanHat++;
}
else if (ch == 'H'){
quanPatch++;
}
else if (ch == 'M'){
quanMap++;
}
else if (ch == 'S'){
quanSword++;
}
else if (ch == 'T'){
quanShirt++;
}
else if (ch == 'Q'){
count++;
System.out.println("Pirate Trading Post");
System.out.println(quanEight + " Genuine Piece Of Eight\n " + quanHat + " Pirate Hat\n " + quanPatch +
" Eye Patch\n " + quanSword + " Sword\n " + quanMap + " Treasure Map\n " + quanShirt + " T-Shirt\n ");
System.out.println("Total: " + purchaseAmount + " bits");
return purchaseAmount;
}
}
}
The problem is a compile problem with this:
int count = 0;
while (count != 0){ // count **IS** 0, does not enter
// your stuff
}
// no return
If with the return command you intend to return the purchaseAmount to the caller of getShoppingList() method, I suggest you moving the return to the end of the method and putting a break in its while instead of purchaseAmount. Like this:
while (count != 0){
// your stuff
if (...) {
// ...
} else if (ch == 'Q'){
// ...
break;
}
}
return purchaseAmount;

How the consecutive numbers can be replaced with the range of number and random number should be as it is?

If there are numbers in which some are in sequence and some are random number, then how the consecutive numbers can be replaced with the range of number and random number should be as it is?
for eg: 1,2,3,4,5,6, 458,243
output: 1-6,458,243
I have just solved this problem..Its super simple just some if-else condition, however, I don't think about efficient way, so please follow the solution and try to efficient it.
public static void main(String[] args) {
int [] numberList = {1,2,3,4,5,6,458,243};
int initialSequence = -1;
int endSequence = -5;
for (int num = 0; num<numberList.length;num++) {
if(num<numberList.length-1) {
if(initialSequence == -1 && numberList[num] == numberList[num+1]-1) {
initialSequence = endSequence = numberList[num];
}else if(initialSequence == -1 && numberList[num] != numberList[num+1]-1){
System.out.print(numberList[num] + " ");
}else if(initialSequence != -1 && numberList[num] == numberList[num+1]-1) {
endSequence = numberList[num];
}
else {
System.out.print(initialSequence + "-" + (endSequence+1) + " ");
initialSequence = -1;
endSequence = -5;
}
}else {
if(initialSequence == -1) System.out.print(numberList[num] + " ");
else {
System.out.print(initialSequence + "-" + (endSequence+1) + " ");
}
}
}
}

not evaluation doubles

Okay so I am sending doubles value to this and its not parsing them as doubles instead it is completely ignoring the decimal values. here is my code if I enter 2.0 + 5.0 it makes it 2 0 5 0 +. =(
import java.beans.Expression;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Infix2Postfix {
private static String grabDigits(String s, int start){
String num = "";
for(int i=start; i < s.length(); i++){
char ch = s.charAt(i);
if(Character.isDigit(ch))
num += ch;
else
return num;
}
return num;
}
private static Double apply(Double a, char op, Double b){
switch(op){
case '+' : return a + b;
case '-' : return a - b;
case '*' : return a * b;
case '/' : return b == 0 ? null : a / b;
default:
return null;
}
}
public static Double evalPostfix(String expr){
Stack<Double> s = new Stack<Double>();
for(int i=0; i<expr.length(); ){
char ch = expr.charAt(i);
if(Character.isDigit(ch)){
String numStr = grabDigits(expr, i);
i += numStr.length();
Double value;
if(isColmn(numStr)){
value = getvaluefromcolmn(numStr);
}else{
value = Double.parseDouble(numStr);
}
s.push(value);
}
else {
if(isOp(ch)){
if(s.size() < 2) return null;
Double b = s.pop(); // right arg
Double a = s.pop(); // left arg
s.push(apply(a, ch, b));
}
else if(!Character.isWhitespace(ch))
return null;
i++; // consume individual char
}
}
if(s.size() != 1) return null;
return s.pop();
}
private static Double getvaluefromcolmn(String numStr) {
// TODO Auto-generated method stub
return null;
}
private static boolean isColmn(String numStr) {
// TODO Auto-generated method stub
return false;
}
private static int prec(char op){
switch(op){
case '+' :
case '-' :
return 0;
case '*' :
case '/' :
return 1;
default:
return -1;
}
}
private static boolean isOp(char ch){
return prec(ch) != -1;
}
public static String infix2postfix(String expr) {
Stack<Character> s = new Stack<Character>();
String pExpr = "";
int numOperands = 0;
int numOperators = 0;
for(int i=0; i<expr.length(); i++){
char ch = expr.charAt(i);
if(Character.isDigit(ch)){
pExpr += " " + ch;
// could have used the grabDigits method here ...
while(i+1 < expr.length() && Character.isDigit(expr.charAt(i+1))){
pExpr += expr.charAt(i+1);
i++;
}
numOperands++;
}
else if (ch == '(')
s.push(ch);
else if (ch == ')'){
while(!s.empty() && s.peek() != '('){
pExpr = pExpr + " " + s.pop() + " ";
numOperators++;
}
if(s.empty())
return "no matching open paren";
if(numOperators >= numOperands)
return "too many operators";
s.pop();
}
else if(isOp(ch)){
// pop operators with same or higher precedence
while(!s.empty() && isOp(s.peek()) && prec(s.peek()) >= prec(ch)){
pExpr = pExpr + " " + s.pop();
numOperators++;
}
if(numOperators >= numOperands)
return "too many operators";
s.push(ch);
}
// else white space - do nothing
}
while(!s.empty()){
char op = s.pop();
if(!isOp(op))
return "error";
pExpr += " " + op;
}
return pExpr;
}
public static void exp(String expr, ArrayList<ArrayList<Comparable<?>>> entries){
expr.replace("(", " ( ");
expr.replace(")", " ) ");
expr.replace("+", " + ");
expr.replace(" - ", " - ");
expr.replace("/", " / ");
expr.replace("*", " * ");
System.out.println("infix: " + expr);
System.out.println("this is at expreesion after replacing "+ expr);
System.out.println("postfix: " + infix2postfix(expr));
System.out.println("--------");
}
public static void main(String [] args){
Scanner kbd = new Scanner(System.in);
// ArrayList<int> tst;
ArrayList<Integer> tst2;
System.out.print("> ");
while(kbd.hasNextLine()){
String expr = kbd.nextLine();
expr = expr.replaceAll("\\s+","");
System.out.println(expr);
Pattern pattern = Pattern.compile("\\s+");
Matcher matcher = pattern.matcher(expr);
boolean check = matcher.find();
String str = matcher.replaceAll(" ");
expr = expr.replace("(", " ( ");
expr =expr.replace(")", " ) ");
expr =expr.replace("+", " + ");
expr =expr.replace("-", " - ");
expr =expr.replace("/", " / ");
expr =expr.replace("*", " * ");
String[] exprArray = expr.split(" ");
System.out.println(str+ " this is expr "+exprArray[1]);
System.out.println(expr);
ArrayList<ArrayList<Comparable<?>>> entries = null;
String pExpr = infix2postfix(expr);
//System.out.println(evalPostfix(expr));
System.out.println(" postfix version: " + pExpr);
System.out.println(" eval(\"" + pExpr + "\"): " + evalPostfix(pExpr));
System.out.print("> ");
}
}
}
I didn't check your code in detail but the following line
while(i+1 < expr.length() && Character.isDigit(expr.charAt(i+1))) ...
looks like you are parsing only digits but not '.' for each expression.
The same holds true for your method grabDigits.
By stopping at the first non-digit you are stopping at the decimal point, and therefore ignoring both it and everything after it.
Don't convert strings to doubles with your own code, use Double.parseDouble().

java rpn calculator

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();
}

Categories