1. 改进的 Test 类
java
import java.util.*;
public class Test {
public static void main(String[] args) {
System.out.println("真值表生成器");
System.out.println("支持的运算符: !(非), &(与), |(或), ->(蕴含), <->(双条件)");
System.out.println("支持的变量: 任意小写字母 (a-z)");
System.out.println("示例: ((a->b)&(!c))");
Scanner input = new Scanner(System.in);
System.out.print("请输入命题公式: ");
String formula = input.nextLine().replace(" ", ""); // 去除空格
// 提取所有变量并按字母顺序排序
Set<Character> variables = extractVariables(formula);
List<Character> sortedVariables = new ArrayList<>(variables);
Collections.sort(sortedVariables);
System.out.println("\n变量: " + sortedVariables);
System.out.println("真值表:");
// 打印表头
printHeader(sortedVariables, formula);
// 生成并打印真值表
TruthTable truthTable = new TruthTable();
truthTable.generateTruthTable(sortedVariables, formula);
}
// 提取公式中的所有变量
private static Set<Character> extractVariables(String formula) {
Set<Character> variables = new HashSet<>();
for (char c : formula.toCharArray()) {
if (Character.isLowerCase(c)) {
variables.add(c);
}
}
return variables;
}
// 打印表头
private static void printHeader(List<Character> variables, String formula) {
// 打印变量名
for (char var : variables) {
System.out.print(var + "\t");
}
// 打印公式
System.out.println(formula);
// 打印分隔线
for (int i = 0; i < variables.size(); i++) {
System.out.print("---\t");
}
System.out.println("---".repeat(Math.max(1, formula.length() / 2)));
}
}
2. 改进的 TruthTable 类
java
import java.util.*;
public class TruthTable {
private Map<Character, Boolean> variableValues;
public void generateTruthTable(List<Character> variables, String formula) {
variableValues = new HashMap<>();
boolean[] assignments = new boolean[variables.size()];
generateAssignments(variables, formula, assignments, 0);
}
// 递归生成所有可能的真值赋值
private void generateAssignments(List<Character> variables, String formula,
boolean[] assignments, int index) {
if (index == variables.size()) {
// 为当前赋值创建变量映射
for (int i = 0; i < variables.size(); i++) {
variableValues.put(variables.get(i), assignments[i]);
}
// 打印当前赋值和计算结果
printAssignment(variables, assignments);
boolean result = evaluateExpression(formula);
System.out.println(result ? "1" : "0");
return;
}
// 递归生成所有可能的赋值
assignments[index] = false;
generateAssignments(variables, formula, assignments, index + 1);
assignments[index] = true;
generateAssignments(variables, formula, assignments, index + 1);
}
// 打印当前的真值赋值
private void printAssignment(List<Character> variables, boolean[] assignments) {
for (int i = 0; i < variables.size(); i++) {
System.out.print(assignments[i] ? "1\t" : "0\t");
}
}
// 计算表达式的真值
public boolean evaluateExpression(String expression) {
// 将表达式转换为后缀表达式(逆波兰表示法)
List<String> postfix = infixToPostfix(expression);
return evaluatePostfix(postfix);
}
// 中缀表达式转后缀表达式
private List<String> infixToPostfix(String expression) {
List<String> output = new ArrayList<>();
Stack<Character> operators = new Stack<>();
for (int i = 0; i < expression.length(); i++) {
char c = expression.charAt(i);
if (Character.isLowerCase(c)) {
// 变量
output.add(String.valueOf(c));
} else if (c == '!') {
// 非运算符(单目)
operators.push(c);
} else if (isOperator(c)) {
// 双目运算符
while (!operators.isEmpty() && precedence(operators.peek()) >= precedence(c)) {
output.add(String.valueOf(operators.pop()));
}
operators.push(c);
} else if (c == '(') {
operators.push(c);
} else if (c == ')') {
while (!operators.isEmpty() && operators.peek() != '(') {
output.add(String.valueOf(operators.pop()));
}
operators.pop(); // 弹出 '('
}
// 处理多字符运算符 (->, <->)
else if (c == '-') {
// 跳过下一个字符 '>'
i++;
operators.push('→');
} else if (c == '<') {
// 跳过 "- >"
i += 2;
operators.push('↔');
}
}
while (!operators.isEmpty()) {
output.add(String.valueOf(operators.pop()));
}
return output;
}
// 计算后缀表达式
private boolean evaluatePostfix(List<String> postfix) {
Stack<Boolean> stack = new Stack<>();
for (String token : postfix) {
if (token.length() == 1 && Character.isLowerCase(token.charAt(0))) {
// 变量
stack.push(variableValues.get(token.charAt(0)));
} else {
char op = token.charAt(0);
if (op == '!') {
// 非运算
boolean operand = stack.pop();
stack.push(!operand);
} else {
// 双目运算
boolean right = stack.pop();
boolean left = stack.pop();
stack.push(applyOperator(left, right, op));
}
}
}
return stack.pop();
}
// 应用运算符
private boolean applyOperator(boolean left, boolean right, char operator) {
switch (operator) {
case '&': // 与
return left && right;
case '|': // 或
return left || right;
case '→': // 蕴含
return !left || right; // p→q 等价于 !p | q
case '↔': // 双条件
return left == right;
default:
throw new IllegalArgumentException("未知运算符: " + operator);
}
}
// 判断是否为运算符
private boolean isOperator(char c) {
return c == '&' || c == '|' || c == '!' || c == '→' || c == '↔';
}
// 运算符优先级
private int precedence(char operator) {
switch (operator) {
case '!': return 4; // 非最高
case '&': return 3; // 与
case '|': return 2; // 或
case '→': return 1; // 蕴含
case '↔': return 0; // 双条件最低
default: return -1;
}
}
}
3. 更高级的版本(支持更多特性)
java
import java.util.*;
public class AdvancedTruthTable {
private Map<Character, Boolean> variableValues;
private List<String> calculationSteps;
public void generateDetailedTruthTable(String formula) {
// 提取变量
Set<Character> variables = new TreeSet<>();
for (char c : formula.toCharArray()) {
if (Character.isLowerCase(c)) variables.add(c);
}
List<Character> varList = new ArrayList<>(variables);
System.out.println("命题公式: " + formula);
System.out.println("变量: " + varList);
System.out.println();
// 打印详细表头
printDetailedHeader(varList, formula);
// 生成真值表
variableValues = new HashMap<>();
calculationSteps = new ArrayList<>();
generateDetailedTable(varList, formula, new boolean[varList.size()], 0);
}
private void printDetailedHeader(List<Character> variables, String formula) {
// 变量列
for (char var : variables) {
System.out.print(var + "\t");
}
// 公式列
System.out.print(formula + "\t");
// 计算步骤
System.out.println("计算过程");
// 分隔线
int totalWidth = variables.size() * 3 + formula.length() + 10;
System.out.println("-".repeat(totalWidth));
}
private void generateDetailedTable(List<Character> variables, String formula,
boolean[] assignments, int index) {
if (index == variables.size()) {
// 设置变量值
for (int i = 0; i < variables.size(); i++) {
variableValues.put(variables.get(i), assignments[i]);
}
// 打印赋值
for (boolean assignment : assignments) {
System.out.print(assignment ? "1\t" : "0\t");
}
// 计算并打印结果
calculationSteps.clear();
boolean result = evaluateWithSteps(formula);
System.out.print(result ? "1\t\t" : "0\t\t");
// 打印计算步骤
System.out.println(String.join(" → ", calculationSteps));
return;
}
assignments[index] = false;
generateDetailedTable(variables, formula, assignments, index + 1);
assignments[index] = true;
generateDetailedTable(variables, formula, assignments, index + 1);
}
private boolean evaluateWithSteps(String expression) {
List<String> postfix = infixToPostfix(expression);
return evaluatePostfixWithSteps(postfix);
}
private boolean evaluatePostfixWithSteps(List<String> postfix) {
Stack<Boolean> stack = new Stack<>();
Stack<String> stepStack = new Stack<>();
for (String token : postfix) {
if (token.length() == 1 && Character.isLowerCase(token.charAt(0))) {
boolean value = variableValues.get(token.charAt(0));
stack.push(value);
stepStack.push(token + "=" + (value ? "1" : "0"));
} else {
char op = token.charAt(0);
if (op == '!') {
boolean operand = stack.pop();
String operandStep = stepStack.pop();
boolean result = !operand;
stack.push(result);
String step = "!" + operandStep + "=" + (result ? "1" : "0");
stepStack.push(step);
calculationSteps.add(step);
} else {
boolean right = stack.pop();
boolean left = stack.pop();
String rightStep = stepStack.pop();
String leftStep = stepStack.pop();
boolean result = applyOperator(left, right, op);
stack.push(result);
String step = "(" + leftStep + op + rightStep + ")=" + (result ? "1" : "0");
stepStack.push(step);
calculationSteps.add(step);
}
}
}
return stack.pop();
}
// 复用之前的辅助方法
private List<String> infixToPostfix(String expression) {
List<String> output = new ArrayList<>();
Stack<Character> operators = new Stack<>();
for (int i = 0; i < expression.length(); i++) {
char c = expression.charAt(i);
if (Character.isLowerCase(c)) {
output.add(String.valueOf(c));
} else if (c == '!') {
operators.push(c);
} else if (isOperator(c)) {
while (!operators.isEmpty() && precedence(operators.peek()) >= precedence(c)) {
output.add(String.valueOf(operators.pop()));
}
operators.push(c);
} else if (c == '(') {
operators.push(c);
} else if (c == ')') {
while (!operators.isEmpty() && operators.peek() != '(') {
output.add(String.valueOf(operators.pop()));
}
operators.pop();
} else if (c == '-') {
i++;
operators.push('→');
} else if (c == '<') {
i += 2;
operators.push('↔');
}
}
while (!operators.isEmpty()) {
output.add(String.valueOf(operators.pop()));
}
return output;
}
private boolean applyOperator(boolean left, boolean right, char operator) {
switch (operator) {
case '&': return left && right;
case '|': return left || right;
case '→': return !left || right;
case '↔': return left == right;
default: throw new IllegalArgumentException("未知运算符: " + operator);
}
}
private boolean isOperator(char c) {
return c == '&' || c == '|' || c == '!' || c == '→' || c == '↔';
}
private int precedence(char operator) {
switch (operator) {
case '!': return 4;
case '&': return 3;
case '|': return 2;
case '→': return 1;
case '↔': return 0;
default: return -1;
}
}
}
4. 使用示例
java
public class TruthTableDemo {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("选择模式:");
System.out.println("1. 基础真值表");
System.out.println("2. 详细计算过程");
System.out.print("请输入选择 (1 或 2): ");
int choice = input.nextInt();
input.nextLine(); // 消耗换行符
System.out.print("请输入命题公式: ");
String formula = input.nextLine().replace(" ", "");
if (choice == 1) {
// 基础版本
Set<Character> variables = new TreeSet<>();
for (char c : formula.toCharArray()) {
if (Character.isLowerCase(c)) variables.add(c);
}
List<Character> varList = new ArrayList<>(variables);
TruthTable tt = new TruthTable();
tt.generateTruthTable(varList, formula);
} else {
// 详细版本
AdvancedTruthTable att = new AdvancedTruthTable();
att.generateDetailedTruthTable(formula);
}
}
}
主要改进点
1. 变量处理
- 自动提取所有小写字母作为变量
- 支持任意数量的变量(不再限制为a-j)
- 变量按字母顺序自动排序
2. 运算符支持
!或¬:非&或∧:与|或∨:或->或→:蕴含<->或↔:双条件
3. 算法改进
- 使用逆波兰表示法(后缀表达式)进行求值
- 正确处理运算符优先级
- 支持复杂的嵌套表达式
4. 用户体验
- 清晰的表头显示
- 可选的计算过程展示
- 更好的错误处理
5. 测试示例
text
输入: ((a->b)&(!c))
输出:
a b c ((a->b)&(!c))
--- --- --- ---------------
0 0 0 1
0 0 1 0
0 1 0 1
0 1 1 0
1 0 0 0
1 0 1 0
1 1 0 1
1 1 1 0
这个改进版本消除了您原代码的限制,现在可以处理任意变量、复杂的嵌套表达式,并且提供了更好的可读性和可扩展性。