public static void main(String[] args) {
// 支持括号 小数 负数
String statement = "-10/(4.5+5.5)*(-4-6+20)/-2"; // 10/(-2) 也行
System.out.println(calculate(statement));
}
@SuppressWarnings("unchecked")
private static double calculate(String statement){
Object[] result = filter(statement);
// 运算数字
List<Double> numList = (List) result[0];
// 运算符
List<Character> symbolList = (List) result[1];
while (!symbolList.isEmpty()) {
int index = symbolList.indexOf('(');
if (index == -1) {
// 没有括号正常运算
realCalculate(numList, symbolList);
} else {
int right = symbolList.indexOf(')');
if (right == index + 1) {
// 括号内的值都取完了,删除括号
symbolList.remove(index);
symbolList.remove(index);
continue;
}
// 左右括号齐全 先算括号内的
if (right != -1) {
List<Double> doubles = numList.subList(index, right);
List<Character> subChars = symbolList.subList(index + 1, right);
realCalculate(doubles, subChars);
}
}
}
return numList.get(0);
}
/**
* @return 一个包含数字的列表和一个包含运算符的列表
*/
private static Object[] filter(String statement) {
// 形式 123,456,789 可能会有空字符串
StringBuilder nums = new StringBuilder();
// 符号列表
List<Character> symbolList = new LinkedList<>();
for (int i = 0; i < statement.length(); i++) {
char c = statement.charAt(i);
if (c == '-' && (i == 0 || statement.charAt(i - 1) == '('
|| statement.charAt(i - 1) == '*' || statement.charAt(i - 1) == '/')) {
nums.append(c).append(statement.charAt(i + 1));
i++;
} else if (Character.isDigit(c) || c == '.') {
nums.append(c);
} else {
symbolList.add(c);
nums.append(',');
}
}
String[] ss = nums.toString().split(",");
List<Double> numList = new ArrayList<>();
for (String num : ss) {
if (!num.isEmpty()) {
numList.add(Double.parseDouble(num));
}
}
return new Object[]{numList, symbolList};
}
private static void realCalculate(List<Double> numList, List<Character> symbolList) {
while (!symbolList.isEmpty()) {
int index = symbolList.indexOf('*'), tmp;
double value = 0.0D;
if (index != -1 && (tmp = symbolList.indexOf('/')) != -1) {
// 同时出现 * / 从左至右运算
if (index < tmp) {
value = numList.remove(index) * numList.remove(index);
} else {
index = tmp;
value = numList.remove(index) / numList.remove(index);
}
} else if (index != -1) {
value = numList.remove(index) * numList.remove(index);
} else if ((index = symbolList.indexOf('/')) != -1) {
value = numList.remove(index) / numList.remove(index);
} else if ((index = symbolList.indexOf('+')) != -1 && (tmp = symbolList.indexOf('-')) != -1) {
// 同时出现 + - 从左至右运算
if (index < tmp) {
value = numList.remove(index) + numList.remove(index);
} else {
index = tmp;
value = numList.remove(index) - numList.remove(index);
}
} else if (index != -1) {
value = numList.remove(index) + numList.remove(index);
} else if ((index = symbolList.indexOf('-')) != -1) {
value = numList.remove(index) - numList.remove(index);
}
// 删除运算符
symbolList.remove(index);
// 将计算结果放回列表,待下次计算
numList.add(index, value);
}
}
总结一下
我的方法是先从括号的算起,根据运算符索引查找运算数索引,从而进行计算,算完后删除运算符和运算数,并将运算结果放回待运算的列表
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。