public class Kalkulator { //---------------------------------------------------------- // Dozvoljene funkcije //---------------------------------------------------------- private static String funkcije[] = {"sqrt", "abs", "ln", "cos", "sin", "tg"}; //---------------------------------------------------------- // Metod koji sredjuje string prema nasim potrebama //---------------------------------------------------------- private static String sredi(String s) { // Pretvaramo sva slova u mala s = s.toLowerCase(); // Ostavljamo samo obicne zagrade s = s.replace('[', '('); s = s.replace('{', '('); s = s.replace(']', ')'); s = s.replace('}', ')'); // Uklanjamo sve razmake s = s.replaceAll("\\s", ""); return s; } //---------------------------------------------------------- // Metod koji proverava da li je neki karakter // operacija i vraca njen prioritet //---------------------------------------------------------- private static int operacija(char c) { switch (c) { case '+': case '-': return 1; case '*': case '/': return 2; case '^': return 3; } return 0; } //---------------------------------------------------------- // Metod koji racuna rezultat neke operacije //---------------------------------------------------------- private static double izracunajOperaciju(char c, double a, double b) throws Exception { switch (c) { case '+': return a+b; case '-': return a-b; case '*': return a*b; case '/': if (b == 0) throw new Exception("Deljenje nulom"); return a/b; case '^': return Math.pow(a, b); } throw new Exception("Problem sa operacijama"); } //---------------------------------------------------------- // Metod koji racuna rezultat neke funkcije //---------------------------------------------------------- private static double izracunajFunkciju(String s, String f) throws Exception { double x = izraz(s); if (f.equals("sqrt")) return Math.sqrt(x); if (f.equals("abs")) return Math.abs(x); if (f.equals("ln")) return Math.log(x); if (f.equals("cos")) return Math.cos(x); if (f.equals("sin")) return Math.sin(x); if (f.equals("tg")) return Math.tan(x); throw new Exception("Problem sa funkcijama"); } //---------------------------------------------------------- // Glavni rekurzivni metod za racunanje vrednosti izraza //---------------------------------------------------------- private static double izraz(String s) throws Exception { if (s.length() == 0) throw new Exception("Lose formiran izraz"); // System.out.println(s); int prvaOtvorenaZagrada = -1; int poslednjaZatvorenaZagrada = -1; int dubinaZagrada = 0; int poslednjaOperacija = -1; int duzina = s.length(); char c; //-------------------------------------------------------------- // Posmatramo zagrade i poslednju operaciju koja ce se izvrsiti //-------------------------------------------------------------- for (int i = duzina-1; i >= 0; i--) { c = s.charAt(i); if (c == ')') { dubinaZagrada++; if (poslednjaZatvorenaZagrada == -1) poslednjaZatvorenaZagrada = i; } if (c == '(') { dubinaZagrada--; prvaOtvorenaZagrada = i; } // Ako je operacija, da li se poslednja izvrsava if (i > 0 && dubinaZagrada == 0 && operacija(c) > 0) { if (poslednjaOperacija == -1) { poslednjaOperacija = i; } else { if (operacija(c) < operacija(s.charAt(poslednjaOperacija))) poslednjaOperacija = i; } } // Ukoliko zagrade nisu lepo ugnjezdene if (dubinaZagrada < 0) throw new Exception("Nepravilno ugnjezdene zagrade"); } if (dubinaZagrada != 0) throw new Exception("Nepravilno ugnjezdene zagrade"); //-------------------------------------------------------------- // Ako smo nasli neku operaciju koja nije // unarni minus, nju cemo izvrsiti //-------------------------------------------------------------- if (poslednjaOperacija > 0) { double a = izraz(s.substring(0, poslednjaOperacija)); double b = izraz(s.substring(poslednjaOperacija+1, duzina)); return izracunajOperaciju(s.charAt(poslednjaOperacija), a, b); } //-------------------------------------------------------------- // Ako se sve nalazi u zagradi, obradjujemo ono unutra //-------------------------------------------------------------- if (poslednjaOperacija == -1 && prvaOtvorenaZagrada == 0 && poslednjaZatvorenaZagrada == duzina-1) return izraz(s.substring(1, duzina-1)); //-------------------------------------------------------------- // Ako nemamo operacije, mozda imamo unarni minus //-------------------------------------------------------------- if (poslednjaOperacija == -1 && s.charAt(0) == '-') { return -izraz(s.substring(1, duzina)); } //-------------------------------------------------------------- // Mozda je u pitanju neka funkcija //-------------------------------------------------------------- if (poslednjaZatvorenaZagrada == duzina-1) { int brFunkcija = funkcije.length; for (int i = 0; i < brFunkcija; i++) if ( s.startsWith(funkcije[i] + "(") ) return izracunajFunkciju(s.substring(funkcije[i].length()+1, duzina-1), funkcije[i]); } //-------------------------------------------------------------- // Jedino je ostalo moguce da je broj, ili konstanta //-------------------------------------------------------------- if (s.equals("pi")) return Math.PI; if (s.equals("e")) return Math.E; try { return new Double(s); } catch (Exception e) { throw new Exception("Lose formiran izraz"); } } //---------------------------------------------------------- // Glavni metod za racunanje vrednosti //---------------------------------------------------------- public static double izracunaj(String s) throws Exception { s = sredi(s); double d = izraz(s); if (Double.isNaN(d)) throw new Exception("Greska pri racunanju"); return d; } }