字符串的四則運算表達式

	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);
		}
	}

總結一下

我的方法是先從括號的算起,根據運算符索引查找運算數索引,從而進行計算,算完後刪除運算符和運算數,並將運算結果放回待運算的列表

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章