结对项目(calculator java)
Calculator(java)
github项目地址:https://github.com/KID53/cal
简介:命令行程序
项目结对合作成员: 易德康 3118005025 张朝阳 3118005027
一、题目描述
实现一个自动生成小学四则运算题目的命令行程序(也可以用图像界面,具有相似功能)。
二、说明
自然数:0, 1, 2, …。
- 真分数:1/2, 1/3, 2/3, 1/4, 1’1/2, …。
- 运算符:+, −, ×, ÷。
- 括号:(, )。
- 等号:=。
- 分隔符:空格(用于四则运算符和等号前后)。
- 算术表达式:
e = n | e1 + e2 | e1 − e2 | e1 × e2 | e1 ÷ e2 | (e),
其中e, e1和e2为表达式,n为自然数或真分数。
- 四则运算题目:e = ,其中e为算术表达式。
三、需求
- 可以控制生成题目的数量
- 可以控制题目中数值(自然数、真分数和真分数分母)的范围
- 题目不重复
- 生成的题目和答案中分数为真分数
- 整个运算过程不出现负数
- 运算符数量小于等于3
- 支持一万道题目的生成
- 在生成题目的同时,计算出所有题目的答案,并存入执行程序的当前目录下文件
- 支持对给定的题目文件和答案文件,判定答案中的对错并进行数量统计
四、效能分析
最开始表达式数都用的是假分数,怎么让表达式转换为真分数思考了很久,还有如何实现分数的计算也是难点.
还有就是中缀转后缀,虽然数据结构里有讲,可惜当时学的不好没有学懂,又只能重新再看去了解.
除此之外,在如何保证生成的题目答案不出现负数的问题下,我俩进行了大量讨论,最后确定下先调用计算方法看结果是否为负数,是负数则重新生成(浪费了不少性能)但也是个有效的方法.
最消耗性能的类应该是生成后缀表达式的类和计算时的类.
五、设计实现过程
六、代码说明
中缀表达式转后缀表达式
public static String creatSuffixExepression(String str) {
int num=0;
int tmp=0;
int stackLen=0;//栈的长度
String expression="";//输出结果字符串
char element='a';
boolean haveNum= false;//是否有数字
Stack<Character> stack= new Stack<>();//字符栈
str=str+"!";//为了判断结束方便加入!做为字符串结尾
for(int i=0;i<str.length();i++) {
char c = str.charAt(i);
if(isNUm(c)) {
haveNum=true;
tmp=tmp*10+(c-'0');
}else {
if(haveNum) {
haveNum=false;
expression+=tmp;
tmp=0;
}
if(c=='(') {//遇到左括号无条件进栈
num++;
stack.push(c);
}else if(c=='+'||c=='-'||c=='!') { //因为+-优先级最低所以全部弹出
if(num>0) {//如果遇到左括号则停止
stackLen= stack.size();
for(int j=0;j<stackLen;j++) {
element = stack.peek();
if(element=='(') {
break;
}
expression+=stack.pop();
}
}else {//全部弹出;
expression+=' ';
if(stack.size()!=0) {
stackLen = stack.size();
for(int j = 0; j < stackLen; j++ ) {
expression += stack.pop();
}
}
}
if(c=='!') {
break;
}
stack.push(c);
expression+=' ';
}else if(c=='*'||c=='/') {
if(str.charAt(i-1)==' '){
while (!stack.empty() && priority(c) <= priority(stack.peek())){//弹出栈顶优先级大于当前元素的符号;
expression +=' ';
expression += stack.peek();
stack.pop();
}
stack.push(c);
}else {
expression+=c;
}
}else if(c==')') {
if(stack.size()!=0) {
stackLen = stack.size();
for(int j = 0; j < stackLen; j++ ) {
element = stack.pop();
if(element=='(') {
break;
}
expression += element;
}
num--;
}
}else if(c==' ') {//遇到空格则加空格;
expression+=' ';
}
}
}
return expression;
}
中缀表达式的生成
public String timu(){//生成表达式
String str = "";
String str1="";
do {
str = "";
str1 = "";
int t = 0;
Random rand = new Random();
t = rand.nextInt(3) + 2;
String[] number = new String[t];//存放数字
String[] symbol = new String[t-1];//存放运算符号
String[] total = new String[4*t-3];//存放式子
String[] total1 = new String[4*t-3];
for(int i = 0;i < t;i++) {
number[i] = Shu();
}
for(int i = 0;i < t-1;i++) {
symbol[i] = fuhao();
}
for(int i = 0;i < 4*t - 3;i++) {
if(i%4 == 0) {
total[i] = number[i/4];
total1[i] = number[i/4];
}
else if(i%4 == 2) {
int k = (i+2)/4 - 1;
total[i] = symbol[k];
total1[i] = symbol[k];
}
else {total[i] = " ";
total1[i] = " ";
}
}
for(int i = 0;i < 4*t - 3;i++) {
if(total1[i].contains("'")) {
total1[i] = jiafenshu(total1[i]);
}
}
if(t == 4) {
if((symbol[1] == "*"||symbol[1] == "/") && (symbol[0] == "+"||symbol[0] == "-")) {
total[0] = "(" + total[0];
total[4] = total[4] + ")";
total1[0] = "(" + total1[0];
total1[4] = total1[4] + ")";
}
if((symbol[1] == "*"||symbol[1] == "-") && (symbol[2] == "+"||symbol[2] == "-")) {
total[8] = "(" + total[8];
total[12] = total[12] + ")";
total1[8] = "(" + total1[8];
total1[12] = total1[12] + ")";
}
}
for(int i = 0;i < 4*t - 3;i++) {
str = str + total[i];
str1 = str1 + total1[i];
}
}while(Count.count(str1).contains("-"));
return str+" ="+";"+str1;
}
四则运算的方法
public static Num add(Num a, Num b) { //加法
Num c= new Num(1,1);
c.numerator = a.numerator * b.denominator + b.numerator * a.denominator;
c.denominator = a.denominator * b.denominator;
return c;
}
public static Num subtract(Num a, Num b) { //减法
Num c= new Num(1,1);
c.numerator = a.numerator * b.denominator - b.numerator * a.denominator;
c.denominator = a.denominator * b.denominator;
return c;
}
public static Num mul(Num a, Num b) { //乘法
Num c= new Num(1,1);
c.numerator = a.numerator * b.numerator;
c.denominator = a.denominator * b.denominator;
return c;
}
public static Num division(Num a, Num b) { //除法
Num c= new Num(1,1);
c.numerator = a.numerator * b.denominator;
c.denominator = a.denominator * b.numerator;
return c;
}
检查答案与题目
if(path.length>1) {
FileReader fr1 = new FileReader(path[1]);
br1 = new BufferedReader(fr1);
}
for(int i=0;(line = br.readLine())!=null;i++) {
path = line.split("=");
if(path.length>1) {
line4 = path[1];
}
path2 = br1.readLine().split("\\.");
if(path2.length>1) {
line5 = path2[1];
}
if(line4.equals(line5)){
line2 = line2 + i+",";
a++;
}else {
line3 = line3 + i+",";
b++;
}
}
line2=line2.substring(0,line2.length()-1);
line3=line3.substring(0,line3.length()-1);
bw.write("Correct: "+ a + line2 +")");
bw.newLine();
bw.write("Wrong: "+ b + line3 +")");
bw.close();
}
七、测试运行
一万道题目生成
测试答案与题目的正确数
可执行文件
八、PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 30 | 45 |
· Estimate | · 估计这个任务需要多少时间 | 1200 | 1225 |
Development | 开发 | 670 | 1140 |
· Analysis | · 需求分析 (包括学习新技术) | 60 | 90 |
· Design Spec | · 生成设计文档 | 30 | 45 |
· Design Review | · 设计复审 (和同事审核设计文档) | 15 | 30 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 15 | 35 |
· Design | · 具体设计 | 60 | 110 |
· Coding | · 具体编码 | 400 | 740 |
· Code Review | · 代码复审 | 30 | 50 |
· Test | · 测试(自我测试,修改代码,提交修改) | 60 | 40 |
Reporting | 报告 | 50 | 40 |
· Test Report | · 测试报告 | 10 | 10 |
· Size Measurement | · 计算工作量 | 15 | 10 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 25 | 20 |
合计 | 1200 | 1225 |
九、项目小结
张朝阳:
- 这次结对项目的双人合作让我获益良多,两个人之间编写各个模块时的交流尤为重要,两人在各自编写的模块中可以根据对方的代码,在自己的代码中做出相应的修改以便在调用彼此的模块更加符合。
- 比如在我编写生成中缀表达式时,借用合作者设计的计算功能判别生成式子中是否产生负数。总之这次有人带飞,我算是个打杂的,做些较简单的代码设计,重任不在吾身。
易德康:
- 结对项目合作起来肯定要比一个人快啦!!!更容易蹦出灵感
- 同时对项目的分工大家一起讨论也能很快讨论出一个标准化的东西.
- 可以从对方身上学到很多自己没掌握的东西,别人懂得函数你不懂正好可以请教,在测试代码的时候,当局者迷旁观者清,终究是别人找bug比较快.
- 线上结对也有麻烦的地方,如果可以面对面交流的话,各个模块的沟通性就比较好,就不会出现写主函数的时候磕磕碰碰的调用了(咱俩的函数都一样),痛苦.
- 对于经常用的函数仍然有掌握不清的地方,例如split函数遇到"."是不会有输出的,因为这个也卡了不少时间.
- 张朝阳同学对生成表达式的理解比我深刻得多,很快就能找到解决问题的办法,是我还要学习的地方.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本