Polish Notation Implementation - java

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

Related

BaseConversion using Strings and bases 2 - 36

I have a program that prompts the user for a string, an initial base, and a final base. The program works fine for all digits however, when I enter in a string mixed with digits and characters it does not return the correct answer. For example, when I input the string BDRS7OPK48DAC9TDT4, original base: 30, newBase: 36, it should return ILOVEADVANCEDJAVA, but instead I get ILOVEADVANHSC6LTS. I know it's a problem with my algorithm but I cant figure out why it's returning the incorrect conversion.
import java.util.Scanner;
public class BaseConversion {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
String theValue;
String result;
String newNum;
int initialBase;
int finalBase;
String[] parts = args;
if (parts.length > 0) {
theValue = parts[0];
isValidInteger(theValue);
initialBase = Integer.parseInt(parts[1]);
finalBase= Integer.parseInt(parts[2]);
isValidBase(finalBase);
}
else {
System.out.println("Please enter a value: ");
theValue = s.nextLine();
isValidInteger(theValue);
System.out.println("Please enter original base: ");
initialBase = s.nextInt();
System.out.println("Please enter new base: ");
finalBase = s.nextInt();
isValidBase(finalBase);
}
// check it
// isValidInteger(theValue, finalBase);
s.close();
newNum = convertInteger(theValue, initialBase, finalBase);
System.out.println("new number: " + newNum);
}
public static void isValidBase(int finalBase) {
if (finalBase < 2 || finalBase > 36) {
System.out.println("Error: Base must be greater than or equal to 2 & less than or equal to 36");
System.exit(1);
}
}
public static void isValidInteger(String num) {
char chDigit;
num = num.toUpperCase();
for(int d = 0; d < num.length(); d++) {
chDigit = num.charAt(d);
if (!Character.isLetter(chDigit) && !Character.isDigit(chDigit)) {
//System.out.println(chDigit);
System.out.println("Error character is not a letter or number");
System.exit(1);
}
}
}
public static String convertInteger(String theValue, int initialBase, int finalBase) {
double val = 0;
double decDigit = 0;
char chDigit;
// loop through each digit of the original number
int L = theValue.length();
for(int p = 0; p < L; p++) {
// get the digit character (0-9, A-Z)
chDigit = Character.toUpperCase(theValue.charAt(L-1-p));
// get the decimal value of our character
if(Character.isLetter(chDigit)) {
decDigit = chDigit - 'A' + 10;
}
else if (Character.isDigit(chDigit)) {
decDigit = chDigit - '0';
}
else {
System.out.println("Error d");
System.exit(1);
}
// add value to total
val += decDigit * Math.pow(initialBase, p);
}
// determine number of digits in new base
int D = 1;
for( ; Math.pow(finalBase, D) <= val; D++) {}
// use char array to hold new digits
char[] newNum = new char[D];
double pwr;
for(int p = D-1; p >= 0; p--) {
// calculate the digit for this power of newBase
pwr = Math.pow(finalBase, p);
decDigit = Math.floor(val / pwr);
val -= decDigit*pwr;
// store the digit character
if(decDigit <= 9) {
newNum[D - 1 - p] = (char) ('0' + (int)decDigit);
}
else {
newNum[D - 1 - p] = (char) ('A' + (int)(decDigit - 10));
}
}
return new String(newNum);
}
}
The algorithm is correct. Take a closer look instead at the place where you convert the input value to a decimal system and in particular at the limitations of the data type you are using.
Resources that could be helpful:
primitive data types - double point in the list
Floating point arithmetic
Question concerning similar problem
JLS - 4.2.3. Floating-Point Types, Formats, and Values
Hope this points you to the right track.
import java.math.BigInteger;
import java.util.Scanner;
public class BaseConversion {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
String theValue;
String result;
String newNum;
int initialBase;
int finalBase;
String[] parts = args;
if (parts.length > 0) {
theValue = parts[0];
isValidInteger(theValue);
initialBase = Integer.parseInt(parts[1]);
finalBase= Integer.parseInt(parts[2]);
isValidBase(finalBase);
}
else {
System.out.println("Please enter a value: ");
theValue = s.nextLine();
isValidInteger(theValue);
System.out.println("Please enter original base: ");
initialBase = s.nextInt();
System.out.println("Please enter new base: ");
finalBase = s.nextInt();
isValidBase(finalBase);
}
// check it
// isValidInteger(theValue, finalBase);
s.close();
newNum = convertInteger(theValue, initialBase, finalBase);
System.out.println("new number: " + newNum);
}
public static void isValidBase(int finalBase) {
if (finalBase < 2 || finalBase > 36) {
System.out.println("Error: Base must be greater than or equal to 2 & less than or equal to 36");
System.exit(1);
}
}
public static void isValidInteger(String num) {
char chDigit;
num = num.toUpperCase();
for(int d = 0; d < num.length(); d++) {
chDigit = num.charAt(d);
if (!Character.isLetter(chDigit) && !Character.isDigit(chDigit)) {
//System.out.println(chDigit);
System.out.println("Error character is not a letter or number");
System.exit(1);
}
}
}
public static String convertInteger(String theValue, int initialBase, int finalBase) {
BigInteger bigInteger = new BigInteger(theValue,initialBase);
String value = bigInteger.toString(finalBase);
value = value.toUpperCase();
return value;
}
}
Here is the correct solution. The problem was with the data type not the algorithm. I hope this helps anyone dealing with the same type of problem.

Not able to generate all the Kaprekar Number in a range

Though the problem seemed simple, here it is :-
A Kaprekar number is a positive whole number n with d digits, such that when we split its square into two pieces - a right hand piece r with d digits and a left hand piece l that contains the remaining d or d−1 digits, the sum of the pieces is equal to the original number (i.e. l + r = n).
The Task
You are given the two positive integers p and q, where p is lower than q. Write a program to determine how many Kaprekar numbers are there in the range between p and q (both inclusive) and display them all.
Input Format
There will be two lines of input: p, lowest value q, highest value
Constraints:
0<p<q<100000
Output Format
Output each Kaprekar number in the given range, space-separated on a single line. If no Kaprekar numbers exist in the given range, print INVALID RANGE.
I could not clear the test cases in the range
22223
99999
In the above range the follwoing numbers should have been generated :-
77778 82656 95121 99999
Here is my code :-
import java.io.*;
import java.util.*;
public class Solution {
public static void main(String[] args) {
/* Enter your code here. Read input from STDIN. Print output to STDOUT. Your class should be named Solution. */
Scanner scan = new Scanner(System.in);
int p = scan.nextInt();
int q = scan.nextInt();
boolean exist = false;
if(q <= p){
System.out.println("INVALID RANGE");
}
int m = 0,n = 0;
long sqr = 0;
String numb = "";
String[] digits = new String[2];
for(int i = p; i <= q; i++){
if(i == 1)System.out.print(1 + " ");
else{
sqr = i*i;
numb = String.valueOf(sqr);// Changing it into a string.
if(numb.length() % 2 == 0){
digits[0] = numb.substring(0, numb.length()/2);//Splitting it into two parts
digits[1] = numb.substring(numb.length()/2);
}else{
digits[0] = numb.substring(0, (numb.length() - 1)/2);
digits[1] = numb.substring((numb.length() -1)/2);
}
if(digits[0] == "" )
m = 0;
if(digits[1] == "")
n = 0;
if(!digits[1].equals("") && !digits[0].equals("")){
m = Integer.parseInt(digits[0]);
n = Integer.parseInt(digits[1]);
}
if(i == (m + n) ){ //Testing for equality
System.out.print(i + " ");
exist = true;
}
}
}
if(exist == false){// If exist is never modified print Invalid Range.
System.out.println("INVALID RANGE");
}
}
}
import java.util.*;
public class Kaprekar
{
public static void main(String args[])
{
Scanner sc=new Scanner(System.in);
System.out.println("Enter a number");
int num=sc.nextInt();
int sq=num*num; String sq1=Integer.toString(sq);
int mid=(Integer.toString(sq).length())/2;
int rem=sq%((int)Math.pow(10,sq1.length()-mid));
int quo=sq/((int)Math.pow(10,sq1.length()-mid));
int sum=rem+quo;
if(sum==num)
{System.out.println("Kaprekar");}else{System.out.println("Not Kaprecar");}
}
}
Changing the type of Loop index i from int to long fixed the problem.
The square computation of i*i was overflowing the upper limit of int so by changing it to long we were able to get the required computation done.
Thanks to Rup for pointing this out.
The code which cleared all the test cases is here :-
import java.io.*;
import java.util.*;
public class Solution {
public static void main(String[] args) {
/* Enter your code here. Read input from STDIN. Print output to STDOUT. Your class should be named Solution. */
Scanner scan = new Scanner(System.in);
int p = scan.nextInt();
int q = scan.nextInt();
boolean exist = false;
if(q <= p){
System.out.println("INVALID RANGE");
return;
}
int m = 0,n = 0;
long sqr = 0;
String numb = "";
String[] digits = new String[2];
for(long i = p; i <= q; i++){
if(i == 1)System.out.print(1 + " ");
else{
sqr = i*i;
numb = String.valueOf(sqr);
if(numb.length() % 2 == 0){
digits[0] = numb.substring(0, numb.length()/2);
digits[1] = numb.substring(numb.length()/2);
}else{
digits[0] = numb.substring(0, (numb.length() - 1)/2);
digits[1] = numb.substring((numb.length() -1)/2);
}
if(digits[0] == "" )
m = 0;
if(digits[1] == "")
n = 0;
if(!digits[1].equals("") && !digits[0].equals("")){
m = Integer.parseInt(digits[0]);
n = Integer.parseInt(digits[1]);
}
if(i == (m + n) ){
System.out.print(i + " ");
exist = true;
}
}
}
if(exist == false){
System.out.println("INVALID RANGE");
}
}
}
import java.io.*;
import java.math.*;
import java.util.*;
class Kaprekar {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int p = scanner.nextInt();
int q = scanner.nextInt();
long i,n,s,a,c,k,d,e=0;
for(i=p;i<=q;i++)
{
k=i;d=0;
while(k!=0)
{
d++;
k=k/10;
}
c=0;s=0;n=i*i;
while(n!=0)
{
a=n%10;
n=n/10;
s=s+ (int)Math.pow(10,c)*a;
c++;
if(n+s==i&&(c==d||c==d-1)&&s!=0)
{
System.out.print(i+" ");
e++; break;
}
}
}
if(e==0)
{
System.out.println("INVALID RANGE");
}
scanner.close();
}
}

how to find StickNumbers

So I have to read a sequence of numbers from the console ( 1 to 50 numbers), none of which are equal and print out the numbers for which is true that a|b == c|d (example: 5|32 == 53|2), but I get an NubmferFormatException each time. Why?
import java.util.Scanner;
public class StuckNumbers {
public static void main(String[] args) {
// create Scanner
Scanner input = new Scanner(System.in);
// input count and declare array
System.out.println("input number of numbers");
int count = input.nextInt();
int[] numbers = new int[count];
// check if count is between 1 and 50
if (count < 1 && count > 50) {
System.out.println("Wrong input. Input a number between 1 and 50");
count = input.nextInt();
}
// input n numbers
for (int i : numbers) {
i = input.nextInt();
// check if i = j
for (int j : numbers) {
if (i == j) {
System.out
.println("All numbers must be dist75inct. Try again.");
i = input.nextInt();
}
}
}
for (int i = 0; i < count; i++) {
for (int j = 0; j < count; j++) {
if (stuckNumbers(numbers[i], numbers[j]) == stuckNumbers(
numbers[j], numbers[i])) {
System.out.println(i + "|" + j + " == " + j + "|" + i);
}
}
}
input.close();
}
public static int stuckNumbers(int a, int b) {
String firstNum = "a";
String secondNum = "b";
String res = "ab";
int result = Integer.parseInt(res);
return result;
}
}
Look at these lines:
String res = "ab";
int result = Integer.parseInt(res);
"ab" is not a number, so you're going to get a NumberFormatException when you try to parse it as an integer.
Change the firstNum and SecondNum variables from "a" and "b" to Integer.toString(a); OR String.valueOf(a); and similar for b.
public static int stuckNumbers(int a, int b) {
String firstNum = String.valueOf(a);
String secondNum = String.valueOf(b);
String res = "";
res.concat(firstNum);
res.concat(secondNum);
int result = Integer.parseInt(res);
return result;
}
I hope this will remove any Exception being thrown.

Binary to Decimal Java converter

I am creating a code that allows you to convert a binary number to a decimal number and vice versa. I have created a code that converts decimal to binary but can not workout how to implement the binary to decimal aspect.
My code for decimal to binary is below:
import java.util.*;
public class decimalToBinaryTest
{
public static void main (String [] args)
{
int n;
Scanner in = new Scanner(System.in);
System.out.println("Enter a positive interger");
n=in.nextInt();
if(n < 0)
{
System.out.println("Not a positive interger");
}
else
{
System.out.print("Convert to binary is: ");
binaryform(n);
}
}
private static Object binaryform(int number)
{
int remainder;
if(number <= 1)
{
System.out.print(number);
return " ";
}
remainder= number % 2;
binaryform(number >> 1);
System.out.print(remainder);
{
return " ";
}
}
}
An explanation to how the binary to decimal code work would help as well.
I have tried the method of the least significant digit*1 then the next least *1*2 then *1*2*2 but can not get it to work.
Thank you #korhner I used your number system with arrays and if statements.
This is my working code:
import java.util.*;
public class binaryToDecimalConvertor
{
public static void main (String [] args)
{
int [] positionNumsArr= {1,2,4,8,16,32,64,128};
int[] numberSplit = new int [8];
Scanner scanNum = new Scanner(System.in);
int count1=0;
int decimalValue=0;
System.out.println("Please enter a positive binary number.(Only 1s and 0s)");
int number = scanNum.nextInt();
while (number > 0)
{
numberSplit[count1]=( number % 10);
if(numberSplit[count1]!=1 && numberSplit[count1] !=0)
{
System.out.println("Was not made of only \"1\" or \"0\" The program will now restart");
main(null);
}
count1++;
number = number / 10;
}
for(int count2 = 0;count2<8;count2++)
{
if(numberSplit[count2]==1)
{
decimalValue=decimalValue+positionNumsArr[count2];
}
}
System.out.print(decimalValue);
}
}
sample:
00000100
0 - 1
0 - 2
1 - 4
0 - 8
0 - 16
0 - 32
0 - 64
0 - 128
Sum values with bit 1 = 4
Good luck!
int decimal = Integer.parseInt("101101101010111", 2);
or if you prefer to doit your self
double output=0;
for(int i=0;i<str.length();i++){
if(str.charAt(i)== '1')
output=output + Math.pow(2,str.length()-1-i);
}
Here is a program which does that.
Make sure the integers you give to int and not too large.
import java.util.Scanner;
public class DecimalBinaryProgram {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (true){
System.out.println("Enter integer in decimal form (or # to quit):");
String s1 = in.nextLine();
if ("#".equalsIgnoreCase(s1.trim())){
break;
}
System.out.println(decimalToBinary(s1));
System.out.println("Enter integer in binary form (or # to quit):");
String s2 = in.nextLine();
if ("#".equalsIgnoreCase(s2.trim())){
break;
}
System.out.println(binaryToDecimal(s2));
}
}
private static String decimalToBinary(String s){
int n = Integer.parseInt(s, 10);
StringBuilder sb = new StringBuilder();
if (n==0) return "0";
int d = 0;
while (n > 0){
d = n % 2;
n /= 2;
sb.append(d);
}
sb = sb.reverse();
return sb.toString();
}
private static String binaryToDecimal(String s){
int degree = 1;
int n = 0;
for (int k=s.length()-1; k>=0; k--){
n += degree * (s.charAt(k) - '0');
degree *= 2;
}
return n + "";
}
}
Of course for this method binaryToDecimal you can just do:
private static String binaryToDecimal(String s){
int n = Integer.parseInt(s, 2);
return n + "";
}
but I wanted to illustrate how you can do that explicitly.
do you want this?
private double dec(String s, int i) {
if (s.length() == 1) return s.equals("1") ? Math.pow(2, i) : 0;
else return (s.equals("1") ? Math.pow(2, i) : 0) + dec(s.substring(0, s.length() - 1), i - 1);
}
dec("101011101",0);
This is a version of a binary to decimal converter. I have used plenty of comments also. Just taught I would like to share it. Hope it is of some use to somebody.
import java.util.Scanner;
public class BinaryToDecimal
{
public static void main(String args[])
{
Scanner input = new Scanner(System.in);
System.out.println("Enter a binary number: ");
String binary = input.nextLine(); // store input from user
int[] powers = new int[16]; // contains powers of 2
int powersIndex = 0; // keep track of the index
int decimal = 0; // will contain decimals
boolean isCorrect = true; // flag if incorrect input
// populate the powers array with powers of 2
for(int i = 0; i < powers.length; i++)
powers[i] = (int) Math.pow(2, i);
for(int i = binary.length() - 1; i >= 0; i--)
{
// if 1 add to decimal to calculate
if(binary.charAt(i) == '1')
decimal = decimal + powers[powersIndex]; // calc the decimal
else if(binary.charAt(i) != '0' & binary.charAt(i) != '1')
{
isCorrect = false; // flag the wrong input
break; // break from loop due to wrong input
} // else if
// keeps track of which power we are on
powersIndex++; // counts from zero up to combat the loop counting down to zero
} // for
if(isCorrect) // print decimal output
System.out.println(binary + " converted to base 10 is: " + decimal);
else // print incorrect input message
System.out.println("Wrong input! It is binary... 0 and 1's like.....!");
} // main
} // BinaryToDecimal
I've written a converter that accepts both strings and ints.
public class Main {
public static void main(String[] args) {
int binInt = 10110111;
String binString = "10110111";
BinaryConverter convertedInt = new BinaryConverter(binInt);
BinaryConverter convertedString = new BinaryConverter(binString);
System.out.println("Binary as an int, to decimal: " + convertedInt.getDecimal());
System.out.println("Binary as a string, to decimal: " + convertedString.getDecimal());
}
}
public class BinaryConverter {
private final int base = 2;
private int binaryInt;
private String binaryString;
private int convertedBinaryInt;
public BinaryConverter(int b) {
binaryInt = b;
convertedBinaryInt = Integer.parseInt(Integer.toString(binaryInt), base);
}
public BinaryConverter(String s) {
binaryString = s;
convertedBinaryInt = Integer.parseInt(binaryString, base);
}
public int getDecimal() {
return convertedBinaryInt;
}
}
public static void main(String[] args)
{
System.out.print("Enter a binary number: ");
Scanner input = new Scanner(System.in);
long num = input.nextLong();
long reverseNum = 0;
int decimal = 0;
int i = 0;
while (num != 0)
{
reverseNum = reverseNum * 10;
reverseNum = num % 10;
decimal = (int) (reverseNum * Math.pow(2, i)) + decimal;
num = num / 10;
i++;
}
System.out.println(decimal);
}

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