Untitled
unknown
plain_text
23 days ago
8.6 kB
3
Indexable
Never
import java.util.*; public class Calculator { // Bản đồ lưu trữ độ ưu tiên của các toán tử và hàm private static final Map<String, Integer> precedence = new HashMap<>(); // Bản đồ lưu trữ các hằng số như pi và e private static final Map<String, Double> constants = new HashMap<>(); // Khởi tạo các bản đồ với các giá trị cụ thể static { // Thiết lập độ ưu tiên cho các toán tử và hàm precedence.put("+", 1); precedence.put("-", 1); precedence.put("x", 2); // Phép nhân precedence.put("/", 2); // Phép chia precedence.put("%", 2); // Phép chia lấy dư precedence.put("sin", 3); // Hàm sin precedence.put("cos", 3); // Hàm cos precedence.put("tan", 3); // Hàm tan precedence.put("ln", 3); // Hàm ln (logarit tự nhiên) precedence.put("lg", 3); // Hàm lg (logarit cơ số 10) precedence.put("(", 0); // Độ ưu tiên của dấu ngoặc mở // Thiết lập các hằng số constants.put("pi", Math.PI); constants.put("e", Math.E); } // Hàm chính để tính toán biểu thức public static double evaluateExpression(String expression) { // Bước 1: Tokenize - Tách biểu thức thành các token List<String> tokens = tokenize(expression); // Bước 2: Chuyển đổi biểu thức từ dạng trung tố sang hậu tố Queue<String> postfix = toPostfix(tokens); // Bước 3: Tính toán giá trị biểu thức hậu tố return evaluatePostfix(postfix); } // Hàm tokenize - Tách biểu thức thành các token private static List<String> tokenize(String expression) { List<String> tokens = new ArrayList<>(); StringBuilder number = new StringBuilder(); // Để lưu các số hoặc số thập phân StringBuilder function = new StringBuilder(); // Để lưu tên các hàm toán học for (int i = 0; i < expression.length(); i++) { char c = expression.charAt(i); if (Character.isDigit(c) || c == '.') { // Nếu ký tự là số hoặc dấu '.' number.append(c); // Thêm vào number } else { if (number.length() > 0) { // Nếu đã có số được lưu tokens.add(number.toString()); // Thêm số vào danh sách tokens number.setLength(0); // Xóa bộ nhớ tạm number } if (Character.isLetter(c)) { // Nếu ký tự là chữ cái function.append(c); // Thêm vào function } else { if (function.length() > 0) { // Nếu đã có hàm được lưu tokens.add(function.toString()); // Thêm hàm vào danh sách tokens function.setLength(0); // Xóa bộ nhớ tạm function } if (c != ' ') { // Bỏ qua khoảng trắng tokens.add(String.valueOf(c)); // Thêm ký tự vào danh sách tokens } } } } // Xử lý các số hoặc hàm còn sót lại if (number.length() > 0) { tokens.add(number.toString()); } if (function.length() > 0) { tokens.add(function.toString()); } return tokens; } // Hàm chuyển đổi từ trung tố (infix) sang hậu tố (postfix) sử dụng thuật toán Shunting-yard private static Queue<String> toPostfix(List<String> tokens) { Queue<String> output = new LinkedList<>(); Stack<String> operators = new Stack<>(); for (String token : tokens) { if (isNumber(token) || isConstant(token)) { output.add(token); // Nếu token là số hoặc hằng số, thêm vào output } else if (isFunction(token)) { operators.push(token); // Nếu token là hàm, đẩy vào stack } else if (token.equals("(")) { operators.push(token); // Nếu token là dấu ngoặc mở, đẩy vào stack } else if (token.equals(")")) { while (!operators.isEmpty() && !operators.peek().equals("(")) { output.add(operators.pop()); // Đẩy các toán tử trong stack vào output cho đến khi gặp dấu ngoặc mở } operators.pop(); // Bỏ dấu ngoặc mở khỏi stack if (!operators.isEmpty() && isFunction(operators.peek())) { output.add(operators.pop()); // Đẩy hàm vào output nếu có } } else { // Xử lý các toán tử while (!operators.isEmpty() && precedence.get(token) <= precedence.get(operators.peek())) { output.add(operators.pop()); // Đẩy toán tử từ stack vào output dựa trên độ ưu tiên } operators.push(token); // Đẩy toán tử hiện tại vào stack } } while (!operators.isEmpty()) { output.add(operators.pop()); // Đẩy tất cả toán tử còn lại trong stack vào output } return output; } // Hàm tính toán biểu thức hậu tố private static double evaluatePostfix(Queue<String> postfix) { Stack<Double> stack = new Stack<>(); while (!postfix.isEmpty()) { String token = postfix.poll(); if (isNumber(token)) { stack.push(Double.parseDouble(token)); // Nếu token là số, đẩy vào stack } else if (isConstant(token)) { stack.push(constants.get(token)); // Nếu token là hằng số, đẩy giá trị hằng số vào stack } else if (isFunction(token)) { double a = stack.pop(); stack.push(evaluateFunction(token, a)); // Tính toán hàm với tham số từ stack và đẩy kết quả vào stack } else { double b = stack.pop(); double a = stack.pop(); stack.push(evaluateOperator(token, a, b)); // Tính toán phép toán với hai tham số từ stack và đẩy kết quả vào stack } } return stack.pop(); // Giá trị cuối cùng trong stack là kết quả của biểu thức } // Hàm thực hiện các hàm toán học như sin, cos, tan, ln, lg private static double evaluateFunction(String function, double a) { switch (function) { case "sin": return Math.sin(a); case "cos": return Math.cos(a); case "tan": return Math.tan(a); case "ln": return Math.log(a); case "lg": return Math.log10(a); default: throw new IllegalArgumentException("Unknown function: " + function); } } // Hàm thực hiện các phép toán cơ bản như +, -, x, /, % private static double evaluateOperator(String operator, double a, double b) { switch (operator) { case "+": return a + b; case "-": return a - b; case "x": return a * b; case "/": return a / b; case "%": return a % b; default: throw new IllegalArgumentException("Unknown operator: " + operator); } } // Kiểm tra xem token có phải là một số không private static boolean isNumber(String token) { try { Double.parseDouble(token); return true; } catch (NumberFormatException e) { return false; } } // Kiểm tra xem token có phải là một hằng số không private static boolean isConstant(String token) { return constants.containsKey(token); } // Kiểm tra xem token có phải là một hàm toán học không private static boolean isFunction(String token) { return precedence.containsKey(token) && precedence.get(token) == 3; } public static void main(String[] args) { // Test với một biểu thức mẫu String expression = "3 + 5 x ( 2 - 8 ) / 2 + sin(pi / 2)"; System.out.println("Result: " + evaluateExpression(expression)); // Kết quả là 0.0 } }
Leave a Comment