Untitled
unknown
plain_text
a year ago
8.6 kB
10
Indexable
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
}
}Editor is loading...
Leave a Comment