211606342杨艺勇 211606379王熙航
小学生计算
一、预估与实际
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 900 | 900 |
• Estimate | • 估计这个任务需要多少时间 | 20 | 20 |
Development | 开发 | 300 | 300 |
• Analysis | • 需求分析 (包括学习新技术) | 60 | 60 |
• Design Spec | • 生成设计文档 | 30 | 30 |
• Design Review | • 设计复审 | 10 | 10 |
• Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | 10 | 10 |
• Design | • 具体设计 | 120 | 180 |
• Coding | • 具体编码 | 60 | 60 |
• Code Review | • 代码复审 | 30 | 20 |
• Test | • 测试(自我测试,修改代码,提交修改) | 120 | 180 |
Reporting | 报告 | 30 | 30 |
• Test Repor | • 测试报告 | 30 | 30 |
• Size Measurement | • 计算工作量 | 40 | 40 |
• Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 40 | 40 |
合计 900 | 1010 |
二、需求分析
三年级:
- 出现小数加减法,参数至多两位
- 乘法开始出现两位数乘以两位数的乘法
- 除法要求除数至多为两位数,被除数最多为三位
客户要求: - 运算符在2~4个
- 可以加括号
- 减法运算的结果不能有负数
- 除法运算除数不能为0,不能有余数
- 至少存在两个不相同的运算符
经过分析,我认为,这个程序应当:
- 对一二年级的代码进行完善补全
- 小数部分的题目忽略不计
- 数字大小在1000以内,不存在负数
- 舍弃含有余数的除法算数题
三、设计
1. 设计思路
- 这个程序的关键就是能判断符号运算的优先级,并能判断括号的位置和括号起的限制作用
- 随机产生的括号如果加在优先级高的运算符上就没有意义,需要单独列出
2. 实现方案
- 运算符的个数可能是2,3,4个。分成3种情况分类随机生成符号以及数字并将其存入字符串中
- 运算结果利用逆波兰算法求结果
四、编码
1. 调试日志
- 一开始用循环随机来随机决定括号的位置,但是括号有时候会到算式的外面,后来是用来随机的数大了一位,导致括号外出
2. 关键代码
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
String input = sc.nextLine();
sc.close();
StringBuilder sb = new StringBuilder(); //结果
Stack
Map<Character,Integer> opMap = new HashMap(); //运算符优先级
opMap.put('(', 0);
opMap.put('+', 1);
opMap.put('-', 1);
opMap.put('*', 2);
opMap.put('/', 2);
//处理字符串
for(int i=0;i<input.length();i++){
if(input.charAt(i) == '('){ //如果是'('直接压栈
opStack.push('(');
}else if(isOperator(input.charAt(i))){ //如果是运算符
char curOp = input.charAt(i);
if(opStack.isEmpty()) //如果运算符栈是空,就直接压栈
opStack.push(curOp);
else if(opMap.get(curOp) > opMap.get(opStack.peek())) //运算符栈不为空,且当当前运算符的优先级比站内第一个运算符的优先级高的时候,压栈
opStack.push(curOp);
else{ //栈不为空,且运算符的优先级小于等于栈顶元素
for(int j = 0;j<=opStack.size();j++){
char ch = opStack.pop(); //弹出栈内第一个元素
sb.append(ch + " ");
if(opStack.isEmpty()){
opStack.push(curOp);
break;
}else if(opMap.get(curOp) > opMap.get(opStack.peek())){
opStack.push(curOp);
break;
}
}
}
}else if(input.charAt(i) == ')'){ //如果是')'就把站内'('上的元素都弹出栈
for(int j = 0;j<opStack.size();j++){
char c = opStack.pop();
if(c == '(')
break;
else
sb.append(c + " ");
}
}else{ //如果是数字就直接添加
sb.append(input.charAt(i)+" ");
}
}
//把栈内剩余的运算符都弹出站
for(int i = 0;i<=opStack.size();i++){
sb.append(opStack.pop() + " ");
}
System.out.println(sb);
}
private static boolean isOperator(char charAt) {
// TODO Auto-generated method stub
if(charAt == '+'||charAt'-'||charAt'*'||charAt=='/')
return true;
return false;
}
采用逆波兰算法,计算算式的值
3. 代码规范
-
代码中的命名均不能以下划线或美元符号开始,也不能一下划线或美元符号结束。
-
代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式。
-
方法名、参数名、成员变量、局部变量都统一使用 lowerCamelCase 风格,必须遵循驼峰形式。
-
常量命名全部大写,单词键用下划线隔开,力求语义表达完整,不要嫌名字长。
-
类型与中括号紧挨相连来定义数组。
-
POJO类中布尔类型的标量,都不要加is前缀,否则部分框架解析会引起序列化错误。
并人工检查代码是否符合规范
五、测试
- 只输入一个参数100 结果 错误
- 输入-n 10 -grade 1 结果正确
- 输入1000 -n -grade 2 结果 输入格式错误
- 输入-grade 3 -c 10 结果输入格式错误
- 输入-n 10 -grade 002 结果正确
六、总结
结对编程,比一个人操作更体现学习能力;通过这次结对作业,自己觉得还是对这门课有很大的陌生感,深感自己的不足,代码不会写;不懂得问题关键出现在哪里,出现错误不会找出根源,还是希望在以后的学习过程中,加倍努力,多向班级里面的大佬们学习取经,既然选择了,就要坚持下去!