您的位置:首页 > 编程语言 > Java开发

计算表达式 java,最符合人脑计算方式的算法

2018-03-24 03:55 337 查看
对于字符串12+(2*(12*12-12+1)/2+6-9)的计算,依次遍历,拆分为运算数和算法符号,存入栈中,当遇到")"号时,折返到最近的"("号,将折返中的运算符和运算数,从栈取出,进行单独计算,计算完成后,将结果加入到栈中,
按照这样的操作,栈中的"("和")"已经完全去除,直到字符串遍历完。然后对栈中的数据进行简单的运算。
/**
 * 一种简单的 表达式计算代码
 * 
 * @author lihy

 * 
 */
public class Calculator {

public static final String equalsSymbol = "=";
public static final String greaterThanSymbol = ">";
public static final String lessThanSymbol = "<";
public static final String lessAndEqualsSymbol = "<=";
public static final String greaterAndEqualsSymbol = ">=";
public static final String plusSymbol = "+";
public static final String minusSymbol = "-";
public static final String multipleSymbol = "*";
public static final String divisionSymbol = "/";
public static final String StartCurvesSymbol = "(";
public static final String endCurvesSymbol = ")";
// 结束符
public static final String endSymbol = "#";
public static final String[] symbols = { ">=", "<=", ">", "<", "+", "-", "*", "/", "(", ")", "=", "#" };

private static final Map<String, Integer> symbolPriorityMap = new HashMap<String, Integer>();

static {

symbolPriorityMap.put("+", 10);
symbolPriorityMap.put("-", 10);
symbolPriorityMap.put("*", 20);
symbolPriorityMap.put("/", 20);
}

/**
* 计算表达式计算 该方法临时写的,还有待整改

* @param str
* @return
*/
public static String calculate(String str) {
int len = str.length();
// 剩下的字符串
String tempStr0 = str;
Stack<String> stack = new Stack<String>();
Stack<String> tempStack = new Stack<String>();
// 临时存储数值
String tempStr1 = "";
K: for (int i = 0; i < len;) {
tempStr0 = str.substring(i);
boolean isStartWithSymbol = false;
for (String symbolStr : symbols) {

/**
* 当遇到结束的小括号或者结束符
*/
if (tempStr0.startsWith(endCurvesSymbol) || tempStr0.startsWith(endSymbol)) {
isStartWithSymbol = true;
if (StringUtils.isNotEmpty(tempStr1)) {
stack.push(tempStr1);
}

tempStr1 = "";
String tempStr2 = "";
//将栈的数据依次拿出遍历,知道遇到"("号或者栈为空
while (!stack.isEmpty() && !StartCurvesSymbol.equals(tempStr2 = stack.pop())) {
tempStack.push(tempStr2);
}
//括号内的计算表达式栈计算完后,将结果放入到栈空
stack.push(simpleCalculate(tempStack));
i++;
continue K;
}
// 剩下的字符串以符号开头
else if (tempStr0.startsWith(symbolStr)) {
isStartWithSymbol = true;
if (StringUtils.isNotEmpty(tempStr1)) {
stack.push(tempStr1);
}
tempStr1 = "";
stack.push(symbolStr);
int symbol_len = symbolStr.length();
i += symbol_len;
continue K;
}
}
if (!isStartWithSymbol) {
tempStr1 += str.charAt(i);
i++;
}

}
System.out.println(stack);
return stack.pop();
}

/**
* 无括号的以+、-、*、/等数值组成的计算栈,例:11+14-12*12的计算栈是12,*,12,-,14,+11

* 思路:以11+14-12*12为例,拿取11、+、14,查看14后面的运算符为-号,优先级相同;
* 计算为11+14得25,再次取两个为-、12,查看12后面的运算符为*号,*号优先级比-号高,将25、-放入到另一个计算队列A
* 12*12继续计算得144,栈已经计算完成,将该栈放入到计算队列A 计算对列A全部都是有加减法组成的,然后逐步计算

*/
private static String simpleCalculate(Stack<String> stack) {

Queue<String> que = new ConcurrentLinkedQueue<String>();
// 保留按顺序计算的临时结果
String str1 = null;
String str2 = null;
while (!stack.isEmpty()) {
//
if (str1 == null) {
// 获取第一个运算数
str1 = stack.pop();
}
// 获取第一个运算符
str2 = stack.pop();
// 获取第二个运算数
String str3 = stack.pop();
// 如果没有到栈底,则获取第二个运算符
if (!stack.isEmpty()) {
String str4 = stack.peek();
// 如果是乘法 或者 除法
if (symbolPriorityMap.get(str4) > symbolPriorityMap.get(str2)) {
str4 = stack.pop();
que.add(str1);
que.add(str2);
String str5 = stack.pop();
double d = calculate(Double.valueOf(str3), str4, Double.valueOf(str5));
str1 = d + "";
} else {
str1 = calculate(Double.valueOf(str1), str2, Double.valueOf(str3)) + "";
}
} else {
str1 = calculate(Double.valueOf(str1), str2, Double.valueOf(str3)) + "";
}

}
que.add(str1);
String _str1 = null;
while (!que.isEmpty()) {
if (_str1 == null) {
_str1 = que.poll();
}
// 只有一个数据
if (que.isEmpty()) {
return _str1;
}
String _str2 = que.poll();
String _str3 = que.poll();
_str1 = calculate(Double.valueOf(_str1), _str2, Double.valueOf(_str3)) + "";

}
return _str1;

}

/**
* "A+B"、"A*B"等计算

* @param begin
* @param symbol
* @param end
* @return
*/
private static double calculate(double begin, String symbol, double end) {
switch (symbol) {
case plusSymbol:
return begin + end;
case minusSymbol:
return begin - end;
case multipleSymbol:
return begin * end;
case divisionSymbol:
return begin / end;

}
return 0;
}

public static void main(String[] args) {

// 计算表达式 后面添加#作为结束符,可以再优化算法后去掉
calculate("12+(2*(12*12+7*12/4-12+1)/2+6-9)#");

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 计算表达式