// metoda sprawdza poprawność nawiasów w wyrażeniu infiksowym
private boolean czyPoprawneNawiasy() {
// tworzymy stos
Stack<String> stos = new Stack<String>();
// dzielimy wyrażenie infiksowe na części na podstawie separatorów
StringTokenizer st = new StringTokenizer(wyrazenieInfiksowe, "()", true);
// dopóki są elementy w wyrażeniu wejściowym
while(st.hasMoreTokens()) {
// pobieramy element
String s = st.nextToken();
// jeżeli znak jest nawiasem otwierającym odkładamy go na stos
if(s.equals("(")) stos.push(s);
// jeżeli znak jest nawiasem zamykającym porównujemy go z wartością ze stosu
if(s.equals(")")) {
if (stos.isEmpty()) return false;
if (!stos.pop().equals("(")) return false;
}
}
// zwracamy true albo false (stos pusty - wszystkie nawiasy są poprawne)
return stos.isEmpty();
}
Po sprawdzeniu poprawności nawiasów możemy już dokonać obliczenia wartości wyrażenia postfiksowego według następującego algorytmu:- Inicjalizujemy stos,
- Analizujemy wyrażenie postfiksowe od lewej do prawej strony,
- Jeżeli element jest argumentem to odkładamy go na stos,
- Jeżeli element jest operatorem to ściągamy ze stosu dwie wartości, wykonujemy działanie, odkładamy na stos wynik,
- Jeżeli dotarliśmy do końca wyrażenie postfiksowego, ściągamy wartość ze stosu (jest to obliczona wartość wyrażenia postfiksowego).
Wyrażenie infiksowe: (4*2)+(15/3)
Wyrażenie postfiksowe: 4 2 * 15 3 / +
kolejny znak stos operacja
4 4 odkładamy na stos
2 4 2 odkładamy na stos
* 8 ściągamy ze stosu dwie wartości i obliczamy
wartość wyrażenia(4*2), odkładamy ją na stos
15 8 15 odkładamy na stos
3 8 15 3 odkładamy na stos
/ 8 5 ściągamy ze stosu dwie wartości i obliczamy
wartość wyrażenia(15/3), odkładamy ją na stos
+ 13 ściągamy ze stosu dwie wartości i obliczamy
wartość wyrażenia(8+5), odkładamy ją na stos
ściągamy ze stosu wynik końcowy (13)
Obliczona wartość wyrażenia postfiksowego: 13
Poniżej metoda obliczająca wartość wyrażenia postfiksowego. Operujemy na wartościach typu double.// metoda oblicza wartość wyrażenia postfiksowego
private double oblicz() {
// tworzymy pusty stos
Stack<Double> stos = new Stack<Double>();
// dzielimy wyrażenie postfiksowe na elementy na podstawie spacji
StringTokenizer st = new StringTokenizer(wyrazeniePostfiksowe, " ");
// dopóki są elementy w wyrażeniu wejściowym
while(st.hasMoreTokens()) {
// pobieramy element
String s = st.nextToken();
// jeśli element nie jest operatorem (czyli jest wartością)
if (!s.equals("+") && !s.equals("*") && !s.equals("-") && !s.equals("/")) {
// zamieniamy łańcuch na liczbę
double wartosc = Double.parseDouble(s);
// odkładamy wartość na stos
stos.push(wartosc);
}
else {
// jeśli element jest operatorem ściągamy dwie wartości ze stosu
double wartosc1 = stos.pop();
double wartosc2 = stos.pop();
// w zależności od operatora obliczamy wynik i odkładamy go na stos
switch(s.charAt(0)) {
case '*': {stos.push(wartosc2 * wartosc1); break;}
case '+': {stos.push(wartosc2 + wartosc1); break;}
case '-': {stos.push(wartosc2 - wartosc1); break;}
case '/': {stos.push(wartosc2 / wartosc1); break;}
}
}
}
// zwracamy końcowy wynik
return stos.pop();
}
Cała klasa OdwrotnaNotacjaPolska:// wykorzystujemy klasy Scanner, Stack<E> oraz StringTokenizer z pakietu java.util
import java.util.*;
/**
* Odwrotna Notacja Polska
* Zamiana wyrażeń infiksowych na postfiksowe
* @author kodatnik.blogspot.com
*/
public class OdwrotnaNotacjaPolska {
// pola klasy
private String wyrazenieInfiksowe;
private String wyrazeniePostfiksowe;
private double wynik;
// konstruktor dokonuje przypisania polom wyrażeń
public OdwrotnaNotacjaPolska(String wyrazenie) {
this.wyrazenieInfiksowe = wyrazenie;
wyrazeniePostfiksowe = "";
wynik = 0.0;
if(!czyPoprawneNawiasy())
wyrazeniePostfiksowe = "Niepoprawne nawiasy w wyrażeniu infiksowym";
else {
// wywołujemy metodę dokonującą konwersji
infiksNaPostfiks();
wynik = oblicz();
}
}
// metoda zwraca wyrażenie w formie infiksowej
public String pobierzWyrazenieInfiksowe() {
return wyrazenieInfiksowe;
}
// metoda zwraca wyrażenie w formie postfiksowej
public String pobierzWyrazeniePostfiksowe() {
return wyrazeniePostfiksowe;
}
// metoda zwraca obliczoną wartość wyrażenia postfiksowego
public double pobierzWynik() {
return wynik;
}
// metoda sprawdza poprawność nawiasów w wyrażeniu infiksowym
private boolean czyPoprawneNawiasy() {
// tworzymy stos
Stack<String> stos = new Stack<String>();
// dzielimy wyrażenie infiksowe na części na podstawie separatorów
StringTokenizer st = new StringTokenizer(wyrazenieInfiksowe, "()", true);
// dopóki są elementy w wyrażeniu wejściowym
while(st.hasMoreTokens()) {
// pobieramy element
String s = st.nextToken();
// jeżeli znak jest nawiasem otwierającym odkładamy go na stos
if(s.equals("(")) stos.push(s);
// jeżeli znak jest nawiasem zamykającym porównujemy go z wartością ze stosu
if(s.equals(")")) {
if (stos.isEmpty()) return false;
if (!stos.pop().equals("(")) return false;
}
}
// zwracamy true albo false (stos pusty - wszystkie nawiasy są poprawne)
return stos.isEmpty();
}
// metoda konwertuje wyrażenie w postaci infiksowej na postfiksową
// wynik operacji jest zapisywany w polu wyrazeniePostfiksowe
private void infiksNaPostfiks() {
// tworzymy pusty stos
Stack<String> stos = new Stack<String>();
// dzielimy wyrażenie infiksowe na części na podstawie separatorów
StringTokenizer st = new StringTokenizer(wyrazenieInfiksowe, "+-*/()", true);
// dopóki są elementy w wyrażeniu wejściowym
while(st.hasMoreTokens()) {
// pobieramy element
String s = st.nextToken();
// jeżeli element jest operatorem
if( s.equals("+") || s.equals("*") || s.equals("-") || s.equals("/")) {
// sprawdzamy priorytety
while(!stos.empty() && priorytet(stos.peek()) >= priorytet(s))
wyrazeniePostfiksowe += stos.pop() + " ";
// odkładamy operator na stos
stos.push(s);
}
// jeżeli element jest nawiasem otwierającym
else if(s.equals("(")) stos.push(s);
// jeżeli element jest nawiasem zamykającym
else if(s.equals(")")) {
// ściągamy operatory ze stosu, aż do nawiasu otwierajęcego
while(!stos.peek().equals("(")) wyrazeniePostfiksowe += stos.pop() + " ";
// ściągamy nawias otwierający
stos.pop();
}
// jeżeli element nie jest operatorem ani nawiasem dodajemy go do wyrażenia postfiksowego
else wyrazeniePostfiksowe += s + " ";
}
// ściągamy ze stosu pozostałe operatory i dodajemy je do wyrażenia postfiksowego
while(!stos.empty()) wyrazeniePostfiksowe += stos.pop() + " ";
}
// metoda zwraca priorytet operatora
public static int priorytet(String operator) {
// dla '+' i '-' zwracamy 1
if(operator.equals("+") || operator.equals("-")) return 1;
// dla '*' i '/' zwracamy 2
else if(operator.equals("*") || operator.equals("/")) return 2;
// dla pozostałych 0
else return 0;
}
// metoda oblicza wartość wyrażenia postfiksowego
private double oblicz() {
// tworzymy pusty stos
Stack<Double> stos = new Stack<Double>();
// dzielimy wyrażenie postfiksowe na elementy na podstawie spacji
StringTokenizer st = new StringTokenizer(wyrazeniePostfiksowe, " ");
// dopóki są elementy w wyrażeniu wejściowym
while(st.hasMoreTokens()) {
// pobieramy element
String s = st.nextToken();
// jeśli element nie jest operatorem (czyli jest wartością)
if (!s.equals("+") && !s.equals("*") && !s.equals("-") && !s.equals("/")) {
// zamieniamy łańcuch na liczbę
double wartosc = Double.parseDouble(s);
// odkładamy wartość na stos
stos.push(wartosc);
}
else {
// jeśli element jest operatorem ściągamy dwie wartości ze stosu
double wartosc1 = stos.pop();
double wartosc2 = stos.pop();
// w zależności od operatora obliczamy wynik i odkładamy go na stos
switch(s.charAt(0)) {
case '*': {stos.push(wartosc2 * wartosc1); break;}
case '+': {stos.push(wartosc2 + wartosc1); break;}
case '-': {stos.push(wartosc2 - wartosc1); break;}
case '/': {stos.push(wartosc2 / wartosc1); break;}
}
}
}
// zwracamy końcowy wynik
return stos.pop();
}
// metoda zwraca nam łańcuch tekstowy z wyrażeniem
// w formie postfiksowej, oraz wynik
public String toString() {
return wyrazeniePostfiksowe + "\nWynik: " + wynik;
}
}
Poniżej przykład wykorzystania klasy.public class TestONP {
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
System.out.print ("Podaj wyrażenie infiksowe: " );
// pobieramy od użytkownika wyrażenie
String wyrazenie = sc.nextLine();
// tworzymy nowy obiekt klasy OdwrotnaNotacjaPolska
// i przekazujemy do konstruktora pobrane od użytkownika wyrażenie
OdwrotnaNotacjaPolska onp = new OdwrotnaNotacjaPolska(wyrazenie);
// wyświetlamy wyrażenie w postaci postfiksowej
System.out.println ("Wyrażenie postfiksowe: " + onp);
}
}
Wyniki działania aplikacji:Podaj wyrażenie infiksowe: (4*2)+(15/3) Wyrażenie postfiksowe: 4 2 * 15 3 / + Wynik: 13.0
Podaj wyrażenie infiksowe: (3+4)*2) Wyrażenie postfiksowe: Niepoprawne nawiasy w wyrażeniu infiksowym
Podaj wyrażenie infiksowe: ((1+2)-2.5)*8/2 Wyrażenie postfiksowe: 1 2 + 2.5 - 8 * 2 / Wynik: 2.0
Nasza klasa nie obsługuje poprawnie sytuacji wyjątkowych oraz ma małą liczbę operatorów (można się pokusić o dodanie operacji potęgowania, pierwiastkowania czy też funkcji trygonometrycznych).

1 Komentarz - Odwrotna Notacja Polska - część 2
bardzo lubieten blog
Prześlij komentarz
Możesz użyć niektórych tagów HTML, takich jak <b>, <i>, <u>, <a> Nie spamuj :)