四则运算
这个作业属于哪个课程 | 22级计科2班 |
---|---|
这个作业要求在哪里 | 作业要求 |
这个作业目标 | 实现一个自动生成小学四则运算题目的命令行程序 |
团队成员
团队成员 | 学号 |
---|---|
李卓荣 | 3122004440 |
蔡家显 | 3122004815 |
Github地址
PSP表格
PSP2.1 | Person Software Process Stages | 预估耗时(min) | 实际耗时(min) |
---|---|---|---|
Planning | 计划 | 30 | 60 |
.Estimate | 预估这个任务需要多少时间 | 60 | 90 |
.Development | 开发 | 180 | 240 |
· Analysis | 需求分析(包括学习新技术 | 60 | 90 |
· Design Spec | 生成设计文档 | 30 | 30 |
· Design Review | 设计复审 | 20 | 15 |
· Coding Standard | 代码规范(为目前的开发制定合适的规范) | 30 | 20 |
· Design | 具体设计 | 20 | 30 |
· Coding | 具体编码 | 120 | 240 |
· Code Review | 代码复审 | 30 | 40 |
· Test | 测试(自我测试、修改代码、提交修改) | 30 | 40 |
Reporting | 报告 | 30 | 40 |
· Test Report | 测试报告 | 20 | 10 |
· Size Measurement | 计算工作量 | 10 | 10 |
· Postmortem & Process Improvement Plan | 事后总结,并提出过程改进计划 | 30 | 30 |
Total | 合计 | 610 | 915 |
设计过程
输入处理:去除表达式空格,若尾部无结束符'='则添加。
合法性检查:遍历表达式,检查字符合法性、括号匹配、等号数量及位置。
计算过程:初始化栈,遍历表达式,数字入缓存,非数字时处理:数字缓存转整数入数字栈,重置缓存。
比较当前运算符与符号栈顶优先级,低则先运算再压入结果,高则直接压入符号栈。右括号则去括号。
返回结果:数字栈最后一个元素为计算结果。
主体函数
/**
* 解析并计算四则运算表达式,返回计算结果
*
* @param numStr 四则运算表达式
* @return 计算结果
*/
public Fraction calculate(String numStr) {
if (numStr != null) {
//去除空格方便处理
numStr = numStr.replaceAll(" ", "");
} else {
return new Fraction(0);
}
// 如果算术表达式尾部没有‘=’号,则在尾部添加‘=’,表示结束符
if (numStr.length() >= 1 && !('=' == numStr.charAt(numStr.length() - 1))) {
numStr += "=";
}
// 检查表达式是否合法
if (!isStandard(numStr)) {
System.out.println(new Throwable().getStackTrace()[0] + ":" + numStr);
return new Fraction(0);
}
// 初始化栈
fractionStack = new Stack<Fraction>();
operationStack = new Stack<Character>();
// 用于缓存数字,因为数字可能是多位的
StringBuffer nowFractionNum = new StringBuffer();
// 从表达式的第一个字符开始处理
for (int i = 0; i < numStr.length(); i++) {
// 获取一个字符
char nowChar = numStr.charAt(i);
// 若当前字符是数字
if (isNumber(nowChar)) {
// 加入到数字缓存中
nowFractionNum.append(nowChar);
} else {
// 非数字的情况
// 将数字缓存转为字符串
String checkFractionNum = nowFractionNum.toString();
if (!checkFractionNum.isEmpty()) {
// 将数字字符串转为长整型数
int num = Integer.parseInt(checkFractionNum);
// 将数字压栈
fractionStack.push(new Fraction(num));
// 重置数字缓存
nowFractionNum = new StringBuffer();
}
//若当前运算符优先级小于栈尾的优先级,则应当先处理前面运算符
while (!comparePri(nowChar) && !operationStack.empty()) {
// 出栈,取出数字,后进先出
Fraction b = fractionStack.pop();
Fraction a = fractionStack.pop();
// 取出栈尾运算符进行相应运算,并把结果压栈用于下一次运算
switch (operationStack.pop()) {
//处理带分数
case '’':
fractionStack.push(Fraction.with(a, b));
break;
//处理普通运算符
case '+':
fractionStack.push(Fraction.add(a, b));
break;
case '-':
fractionStack.push(Fraction.sub(a, b));
break;
case '×':
case '*':
fractionStack.push(Fraction.mul(a, b));
break;
case '/':
case '÷':
fractionStack.push(Fraction.div(a, b));
break;
default:
break;
}
}
if (nowChar != '=') {
// 符号入栈
operationStack.push(nowChar);
if (nowChar == ')') {
// 去括号
operationStack.pop();
operationStack.pop();
}
}
}
}
return fractionStack.pop();
}
运行结果
性能分析