计算表达式 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)#");
}
}
按照这样的操作,栈中的"("和")"已经完全去除,直到字符串遍历完。然后对栈中的数据进行简单的运算。
/**
* 一种简单的 表达式计算代码
*
* @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
- 算法设计 计算表达式的值 java
- 蓝桥杯 算法训练 表达式计算 Java
- 算法-蓝桥杯-算法训练 表达式计算 (JAVA)
- Java 数据结构和算法 计算表达式问题
- 算法练习 表达式计算(java)
- java数学表达式计算算法
- 算法笔记_044:表达式计算求值(Java)
- 关于java 的科学计算算法(前,中,后缀表达式的转换)——计算器制作的心得
- Java实现表达式计算(中缀表达式转化为后缀表达式/逆波兰式)
- C/C++中算法运行时间的三种计算方式(By 虚怀若谷)
- 数据结构之应用 "栈(Stack)" 实现: 解析算术表达式及计算求值 (C#/Java)
- JAVA常见算法题(三十四)---计算加密之后的电话号码
- 我就给一个PHP逆波兰表达式的算法吧---工资计算专用
- 我就给一个PHP逆波兰表达式的算法吧---工资计算专用
- Java 中缀表达式转后缀表达式 + 中/后缀表达式计算
- 黑马程序员 Java中根据YYYY-MM-DD格式的日期计算为星期几的两种实现方式
- 字符串表达式的计算java版本
- 算法训练 表达式计算 ——蓝桥杯
- java 日历计算农历和节假日的常用类(包括除夕的算法)