User:Margusmartsepp/Contributions/Java/Math2.java

From Rosetta Code

<lang java>import java.util.Scanner; import java.util.Stack;

import com.google.common.collect.ImmutableMap;

public class Math2 { public interface Operator<T> { T apply(final Double Val_1, final Double Val_2); }

public static ImmutableMap<String, Operator<Double>> op2 = new // ImmutableMap.Builder<String, Operator<Double>>// ().put("+", new Operator<Double>() { public Double apply(final Double Val_1, final Double Val_2) { return Val_1 + Val_2; } }).put("-", new Operator<Double>() { public Double apply(final Double Val_1, final Double Val_2) { return Val_1 - Val_2; } }).put("*", new Operator<Double>() { public Double apply(final Double Val_1, final Double Val_2) { return Val_1 * Val_2; } }).put("/", new Operator<Double>() { public Double apply(final Double Val_1, final Double Val_2) { return Val_1 / Val_2; } }).put("^", new Operator<Double>() { public Double apply(final Double Val_1, final Double Val_2) { return Math.pow(Val_1, Val_2); } }).build();

public static String toPostfix(String input) { if (input == null) return ""; char[] in = input.toCharArray(); Stack<Character> stack = new Stack<Character>(); StringBuilder out = new StringBuilder();

for (int i = 0; i < in.length; i++) switch (in[i]) { case '+': case '-': while (!stack.empty() && (stack.peek() == '*' || stack.peek() == '/')) out.append(' ').append(stack.pop()); case '*': case '/': out.append(' '); case '(': stack.push(in[i]); case ' ': break; case ')': while (!stack.empty() && stack.peek() != '(') out.append(' ').append(stack.pop()); if (!stack.empty()) stack.pop(); break; default: out.append(in[i]); break; }

while (!stack.isEmpty()) out.append(' ').append(stack.pop());

return out.toString(); }

public static Double evalPostfix(String input) { Stack<Double> stack = new Stack<Double>(); Scanner sc = new Scanner(input); String s; Double tmp;

while (sc.hasNext()) if (op2.containsKey(s = sc.next())) { tmp = stack.pop(); stack.push(op2.get(s).apply(stack.pop(), tmp)); } else stack.push(Double.parseDouble(s));

return stack.pop(); }

public static Double eval(String input) { return evalPostfix(toPostfix(input)); } } </lang>