Overview

There are many calculator programs on the Internet.
However, most of them do not work well or parentheses are not possible.
The program introduced from now on is a calculator that can be parenthesized.

Change the formula that a person entered into a rear table.
It is taken out of the Stack and switched back to the mid -term mark, and the actual calculation is performed between them.

If you use it, you can add the function you want.
For example, it is easy to add SIN (1), SQRT (1), etc.
If the molecule is divided into zero, the error is done.

 

Code Example

package com.example.test;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class CamelActCalculator {
	static Pattern minusPattern = Pattern.compile("[0-9]{1}[-]{1}[0-9]{1}");
	static Pattern pattern = Pattern.compile("[-]?[0-9]*\\.?[0-9]+|\\(|\\)|\\+|-|\\*|/|(abs)|(log10)|(if)|,|<=|>=|<|>|=|(and)|(or)");

	private static Map<String, Integer> priorityMap = new HashMap<String, Integer>();
	static {
		priorityMap.put("=", 1);
		priorityMap.put("<", 1);
		priorityMap.put(">", 1);
		priorityMap.put("<=", 1);
		priorityMap.put(">=", 1);
		priorityMap.put("and", 1);
		priorityMap.put("or", 1);
		priorityMap.put("+", 2);
		priorityMap.put("-", 2);
		priorityMap.put("*", 3);
		priorityMap.put("/", 3);
		priorityMap.put("(", 0);
	}
	
	public static void main(String[] args) {
		System.out.println(getCalculatedValue("30+20-21"));
		System.out.println(getCalculatedValue("-30+20-21"));
		System.out.println(getCalculatedValue("-30+(-30)"));
		System.out.println(getCalculatedValue("2.0*abs(-30-(-20*2))+20"));
		System.out.println(getCalculatedValue("2*abs(-30-abs(-20*2))+20"));
		System.out.println(getCalculatedValue("2*abs(-30-log10(20*2))+20"));
		System.out.println(getCalculatedValue("if(10<20,1,2)"));
		System.out.println(getCalculatedValue("if(10<20,if(11<22,1,2),3)"));
		System.out.println(getCalculatedValue("if(10+12+abs(20+3-2)<20,1,2)"));
		System.out.println(getCalculatedValue("if((1=0)&(2=0),0,1)"));
		System.out.println(getCalculatedValue("if((((1+3=0)and(30+2)))or(2=0),0,1)"));
		System.out.println(getCalculatedValue("if((1<=0)&(2=0),0,1)"));
		System.out.println(getCalculatedValue("if((1=0)and(2=0)and(3=0),0,if((1=0)or(2=0)or(3=0),100,100-(4/5)*(6/7)*(8/9)*100))"));
		System.out.println(getCalculatedValue("-50/-25"));
		System.out.println(getCalculatedValue("-50/0"));
	}
	
	public static double getCalculatedValue(String param) {
		if(param.contains("NaN")) {
			return Double.NaN;
		}
		
		Matcher m = minusPattern.matcher(param);
		while (m.find()) { 	// 30-20 to 30+-20		but cannot allow 30-(20) to 30+-(20) or -30+20 to +-30+20 or 30-abs(20) to 30+-abs(20)
			String word = m.group();
			String replace = word.charAt(0) + "+-" + word.charAt(2);
			param = param.replace(word, replace);
		}
		
		 Queue<String> infixQue = new LinkedList<String>();
		
		m = pattern.matcher(param);
		while (m.find()) {
			String word = m.group();
			
			if(word.equals("abs") || word.equals("log10")) {
				word = operSpecial(word, m, word.charAt(0)) ;
			} else 	if(word.equals("if")) {
				word = operIf(word, m);
			}
			
			infixQue.add(word);
		}
		
		double num = transformPostfix(infixQue);
		if(Double.isNaN(num)) { // can not divide 0
			System.out.println(Double.NaN + " convert to 0");
			return 0;
		}
		return num;
	}
	
	public static String operIf(String word, Matcher m) {
		Queue<String> conditionQue = new LinkedList<String>();
		Queue<String> trueQue = new LinkedList<String>();
		Queue<String> falseQue = new LinkedList<String>();
		Queue<String> refQue = conditionQue;
		
		int count = 0;
		int que = 0;
		while (m.find()) {
			word = m.group();
			
			if(word.equals("abs") || word.equals("log10")) {
				word = operSpecial(word, m, word.charAt(0)) ;
			} else 	if(word.equals("if")) {
				word = operIf(word, m);
			} else if(word.equals(",") && que == 0) {
				que++;
				refQue = trueQue;
				continue;
			} else if(word.equals(",") && que == 1) {
				que++;
				refQue = falseQue;
				continue;
			} else {
				if (word.equals("(")) {
					count++;
					if (count == 1)
						continue;
				}
				if (word.equals(")")) {
					count--;
					if (count == 0)
						break;
				}
			}
			
			refQue.add(word);
		}
		
		double num = 0f;
		if(transformPostfix(conditionQue) > 0) {
			num = transformPostfix(trueQue);
		} else {
			num = transformPostfix(falseQue);
		}
		
		return num + "";
	}
	
	public static String operSpecial(String word, Matcher m, char c) {
		Queue<String> subInfixQue = new LinkedList<String>();
		int count = 0;
		while (m.find()) {
			word = m.group();
			
			if(word.equals("abs") || word.equals("log10")) {
				word = operSpecial(word, m, word.charAt(0)) ;
			} else 	if(word.equals("if")) {
				word = operIf(word, m);
			} else {
				if (word.equals("(")) {
					count++;
					if (count == 1)
						continue;
				}
				if (word.equals(")")) {
					count--;
					if (count == 0)
						break;
				}
			}
			
			subInfixQue.add(word);
		}

		double num = transformPostfix(subInfixQue);
		
		switch (c) {
		case 'a':
			word = Math.abs(num) + "";
			break;
		case 'l':
			word = Math.log10(num) + "";
			break;
		default:
			word = Math.abs(num) + "";
			break;
		}
		
		return word;
	}

	public static double transformPostfix(Queue<String> param) {
		Stack<String> infixStack = new Stack<String>();
		Queue<String> postfixQue = new LinkedList<String>();
		
		for(String word : param) {
			if (word.equals("(")) {
				infixStack.push(word);
			} else if (priorityMap.containsKey(word)) {
				while (true) {
					if (infixStack.isEmpty() || priorityMap.get(infixStack.peek()) < priorityMap.get(word)) {
						infixStack.push(word);
						break;
					} else {
						String popStr = infixStack.pop();
						postfixQue.add(popStr);
					}
				}
			} else if (word.equals(")")) {
				while (true) {
					String popStr = infixStack.pop();
					if (popStr.equals("(")) {
						break;
					} else {
						postfixQue.add(popStr);
					}
				}
			} else {
				postfixQue.add(word);
			}
		}

		while (infixStack.isEmpty() == false) {
			String popStr = infixStack.pop();
			postfixQue.add(popStr);
		}
		
		double num = calculatePostfix(postfixQue);
		return num;
	}

	public static double calculatePostfix(Queue<String> param) {
		Stack<Double> postfixStack = new Stack<Double>();
		
		double firstVal;
		double secondVal;

		while (param.isEmpty() == false) {
			String word = param.remove();

			if (priorityMap.containsKey(word)) {
				secondVal = postfixStack.pop();
				firstVal = postfixStack.pop();

				switch (word) {
				case "+":
					postfixStack.push(firstVal + secondVal);
					break;
				case "-":
					postfixStack.push(firstVal - secondVal);
					break;
				case "*":
					postfixStack.push(firstVal * secondVal);
					break;
				case "/":
					postfixStack.push(firstVal / secondVal);
					break;
				case "and":
					if(firstVal > 0 && secondVal > 0) {
						postfixStack.push(1.);
					} else {
						postfixStack.push(0.);
					}
					break;
				case "or":
					if(firstVal > 0 || secondVal > 0) {
						postfixStack.push(1.);
					} else {
						postfixStack.push(0.);
					}
					break;
				case "=":
					if(firstVal == secondVal) {
						postfixStack.push(1.);
					} else {
						postfixStack.push(0.);
					}
					break;
				case "<":
					if(firstVal < secondVal) {
						postfixStack.push(1.);
					} else {
						postfixStack.push(0.);
					}
					break;
				case ">":
					if(firstVal > secondVal) {
						postfixStack.push(1.);
					} else {
						postfixStack.push(0.);
					}
					break;
				case "<=":
					if(firstVal <= secondVal) {
						postfixStack.push(1.);
					} else {
						postfixStack.push(0.);
					}
					break;
				case ">=":
					if(firstVal >= secondVal) {
						postfixStack.push(1.);
					} else {
						postfixStack.push(0.);
					}
					break;
				default:
					break;
				}

			} else {
				postfixStack.push(Double.valueOf(word));
			}
		}
		return postfixStack.pop();
	}
}

 

Console Result

29.0
-31.0
-60.0
40.0
160.0
83.20411998265593
1.0
1.0
2.0
1.0
1.0
1.0
39.04761904761905
2.0
-Infinity

 

Conclusion

N/A

728x90

'Java Utility' 카테고리의 다른 글

[ENG][IPv4][IPv6]Using IP Checker  (0) 2022.11.02
[ENG][Mina]Using Apache Mina sshd - shell command line  (0) 2022.08.31

+ Recent posts