java 计算器后台实现
有两种方案,第一种想到了就很简单,调用js脚本
public class CalculatorByJavaScript {
public static void main(String[] args) {
String str = "15*7-(19-18*(11+12))";
//执行JS脚本
ScriptEngine jse = new ScriptEngineManager().getEngineByName("JavaScript");
Object eval;
try {
eval = jse.eval(str);
System.out.println(eval);
if("Infinity".equals(eval.toString())) {
throw new RuntimeException("分母不能为0");
}
} catch (Exception e) {
if(e instanceof javax.script.ScriptException) {
System.out.println(String.format("%s:表达式错误 %n %s" ,str,e.getMessage()));
}else {
System.out.println(e.getMessage());
}
e.printStackTrace();
}
}
}
第二种就是用栈来实现,难点在于表达式中负数的截取:比如3+(-11),(-11)+3
还有就是对 后缀表达式,中缀表达式的理解(不明白的,百度一下)
package com.zh.javaweb.calculator;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Scanner;
import java.util.Stack;
import org.springframework.util.NumberUtils;
/**
* @author zhouhong
* @createDate 2019年1月17日 下午12:10:58
*/
public class CalculatorByJava {
@SuppressWarnings("resource")
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
while (true) {
String mid = scan.nextLine();
if (mid.equals("")) {
System.out.println("已结束输入!");
break;
}
List<String> list = transferToBehind(mid);
BigDecimal comeOut = calculator(list);
System.out.println(comeOut);
}
}
/**
* 将表达式分割,eg:2+66*2 1,+,*,2
* @author: zhouhong
* @date: 2019年1月17日 下午12:24:30
* @param mid
* @return
*/
private static List<String> transferToBehind(String mid) {
//去除前后空格
char[] charArray = mid.trim().toCharArray();
//解析字符数组
String str = transferToStr(charArray);
return transferToList(str);
}
/**
* 把带有1,2+3,,0,-1 字符串转换成 list 去掉中间的空格
* @author: zhouhong
* @date: 2019年1月17日 下午2:23:29
* @param str
* @return
*/
private static List<String> transferToList(String str) {
String[] split = str.split(",");
List<String> asList = new ArrayList<>(Arrays.asList(split));
Iterator<String> iterator = asList.iterator();
while (iterator.hasNext()) {
String next = iterator.next();
if (next == null || " ".equals(next) || "".equals(next)) {
iterator.remove();
}
}
return asList;
}
/**
*
* @author: zhouhong
* @date: 2019年1月17日 下午2:17:34
* @param charArray
* @return
*/
private static String transferToStr(char[] charArray) {
String str = "";
for (int i = 0; i < charArray.length; i++) {
char c = charArray[i];
if (i == 0 && checkNumber(c)) {//判断首位是数字
str = str + c;
continue;
}
if (i == 0 && "-".equals(String.valueOf(c))) {//判断首位是负数-
str = str + "," + c;
continue;
}
if ("(".equals(String.valueOf(c)) || ")".equals(String.valueOf(c))) {//判断是否是括号
str = str + "," + c + ",";
continue;
}
if ("(".equals(String.valueOf(charArray[i - 1])) && checkSymbol(c)) {//判断左括号后面是符号比如(-1) (-
str = str + "," + c+charArray[i=i + 1];
continue;
}
if ("(".equals(String.valueOf(charArray[i - 1])) && checkNumber(c)) {//判断左括号后面是否是数字比如(1) (1
if(checkNumber(charArray[i +1])) {
str = str + "," + c + charArray[i=i + 1];
}else {
str = str + "," + c + ",";
}
continue;
}
if (checkSymbol(c)) {
str = str + "," + c + ",";
}
if (checkNumber(c)) {
str += c;
}
}
return str;
}
private static BigDecimal calculator(List<String> list) {
Stack<String> s1 = new Stack<String>();//用于计算 --后缀表达式
Stack<String> s2 = new Stack<String>();//出栈
pushStack(list, s1);
popStack(s1,s2);
return new BigDecimal(s2.pop());
}
private static void popStack(Stack<String> s1, Stack<String> s2) {
//[9, 3, 1, -, 3, *, +, 10, 2, /, +]
Stack<String> temp = new Stack<String>();
while(!s1.empty()) {
temp.push(s1.pop());
}
while(!temp.empty()) {
if (checkNumber(temp.peek())) { //检查数字
s2.push(temp.pop());
continue;
}
BigDecimal num1 = new BigDecimal(s2.pop());
BigDecimal num2 = new BigDecimal(s2.pop());
switch (temp.pop()) {
case "+":
BigDecimal add = num2.add(num1);
s2.push(String.valueOf(add.intValue()));
break;
case "-":
BigDecimal subtract = num2.subtract(num1);
s2.push(String.valueOf(subtract.intValue()));
break;
case "*":
BigDecimal multiply = num2.multiply(num1);
s2.push(String.valueOf(multiply.intValue()));
break;
case "/":
BigDecimal divide = num2.divide(num1);
s2.push(String.valueOf(divide.intValue()));
break;
default:
break;
}
}
}
private static void pushStack(List<String> list, Stack<String> s1) {
Stack<SymbolEnum> s2 = new Stack<SymbolEnum>();//临时存放运算符 -- 中缀
for (String str : list) {
pushStack(str,s1,s2);
}
while(!s2.isEmpty()) {
s1.push(s2.pop().getType());
}
}
private static void pushStack(String str, Stack<String> s1, Stack<SymbolEnum> s2) {
if (checkNumber(str)) { //检查数字
s1.push(str);
return;
}
if ("(".equals(str)) {//检查左括号
s2.push(SymbolEnum.getValue(str));
return;
}
if (checkSymbol(str.toCharArray()[0])) { //检查运算符
SymbolEnum symbol1 = SymbolEnum.getValue(str);
if (s2.empty()) {
s2.push(symbol1);
}else {
SymbolEnum symbol2 = s2.peek();
if(symbol2.getNum() < 4 ) {
while(!s2.empty() && symbol1.getNum() <=s2.peek().getNum() ) {
s1.push(s2.pop().getType());
}
}
s2.push(symbol1);
}
}
if (")".equals(str)) {//检查右括号
while(!s2.peek().getType().equals("(") ) {
s1.push(s2.pop().getType());
}
s2.pop();//删除左括号
}
}
/**
* 判断是否是运算符 + - * /
* @author: zhouhong
* @date: 2019年1月17日 上午1:34:06
* @param word
* @return
*/
public static boolean checkSymbol(char word) {
if (word == '+' || word == '-' || word == '*' || word == '/') {
return true;
}
return false;
}
/**
* 判断数字
* @author: zhouhong
* @date: 2019年1月17日 上午1:35:58
* @param word
* @return
*/
public static boolean checkNumber(char word) {
if ((word >= '0' && word <= '9') || word == '.') {
return true;
}
return false;
}
public static boolean checkNumber(String word) {
try {
NumberUtils.parseNumber(word, BigDecimal.class);
return true;
}catch(Exception e) {
return false;
}
}
}
enum SymbolEnum {
RIGHT_BRACKETS(")", 8),
LEFT_BRACKETS("(",4),
MULTIPLY("*",2),
EXCEPT("/", 2),
ADD("+",1),
REDUCE("-",1),;
String type;
int num;
public static SymbolEnum getValue(String type) {
for (SymbolEnum symbol : SymbolEnum.values()) {
if(symbol.getType().equals(type)) {
return symbol;
}
}
return null;
}
public static SymbolEnum getValue(int num) {
for (SymbolEnum symbol : SymbolEnum.values()) {
if(symbol.getNum() == num) {
return symbol;
}
}
return null;
}
private SymbolEnum(String type, int num) {
this.type = type;
this.num = num;
}
public String getType() {
return type;
}
public int getNum() {
return num;
}
}

浙公网安备 33010602011771号