一 、Github项目地址:https://github.com/mushan520/Four-fundamental-rules-java.git

                                 或   https://github.com/SAH2019/as

 

二、PSP表格:

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 60   45
· Estimate · 估计这个任务需要多少时间 60 45
Development 开发 1260 1515
· Analysis · 需求分析  60   90  
· Design Spec · 生成设计文档 60 60
· Design Review · 设计复审  30 45
· Coding Standard · 代码规范 30 60
· Design · 具体设计 90 90
· Coding · 具体编码 900 1080
· Code Review · 代码复审 30 30
· Test · 测试(自我测试,修改代码,提交修改) 60 90
Reporting 报告 100 140
· Test Report · 测试报告 30 50
· Size Measurement · 计算工作量 30 50
· Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 40 40
合计   1420 1700

三:实现过程

1.因为涉及到分数的相关运算,所以单独设计了一个分数类Fraction,里面实现了分数的加减乘除计算以及分数的显示,以供给其他的类和方法调用

 2.FormulaMaker中展示了整个项目的实现过程:1)随机生成整数或者分数-->2)随机生成四则运算的符号-->3)将生成的运算数和符号连接成算式-->4)对算式进行结果的计算-->5)分别输出结果和算式到文件中。

3.我们所做的程序和老师的要求还有一定的差距,比如分数的表示,目前我们的程序生成的结果,都是以分数形式表示的,比如0/2  ,2/1或者是8/3这种本该用2‘2/3表示的结果,无法正确的按要求显示,这是我们技术上的不成熟导致的,很遗憾。

  4.以下的导图显示了程序的方法结构。

 

四:代码说明

1.   FormulaMaker :主要的一个类:用来完成生成随机的算式,以及算式的计算,还有算式和答案的输出

  1 package creater;
2
3 import java.io.File;
4 import java.io.FileWriter;
5 import java.io.PrintStream;
6 import java.util.HashSet;
7 import java.util.Random;
8 import java.util.Stack;
9
10 public class FormulaMaker {
11 private int numRange;
12 private int questionsNum;
13
14 public FormulaMaker(int numRange, int questionsNum) {
15 this.numRange = numRange;
16 this.questionsNum = questionsNum;
17 makeFormula();
18 HashSet<String> set = makeFormulas();
19 Fraction[] arr = getAnswers(set);
20 outputFormula(set);
21 outputAnswers(arr);
22
23 }
24
25 // 获取随机整数
26 public int getRandomNumber() {
27 Random rand = new Random();
28 int RandomNum = rand.nextInt(this.numRange);
29 if (RandomNum == 0)
30 RandomNum = RandomNum + 1;
31 return RandomNum;
32 }
33 //获取随机分数
34 public Fraction getRandomFraction() {
35 Fraction a = new Fraction(getRandomNumber(), getRandomNumber());
36 return a;
37
38 }
39
40 // 获取随机运算符号
41 public String getRandomSign() {
42 Random rand = new Random();
43 String[] operations = { "+", "-", "*", "/" };
44 return operations[rand.nextInt(4)];
45 }
46
47 public String makeFormula() {
48 String formula = "";
49 for (int i = 0; i < 4; i++) {
50 if (i >= 3) {
51 {
52 Random rand = new Random();
53 int a = rand.nextInt(2);
54 switch (a) {
55 case 0:
56 formula += this.getRandomNumber();
57 break;
58 case 1:
59 formula += getRandomFraction();
60 break;
61 }
62 }
63 continue;
64 }
65 Random rand = new Random();
66 int a = rand.nextInt(2);
67 switch (a) {
68 case 0:
69 formula += this.getRandomNumber() + " " + this.getRandomSign() + " ";
70 break;
71 case 1:
72 formula += this.getRandomFraction() + " " + this.getRandomSign() + " ";
73 break;
74 }
75
76 }
77 return formula;
78 }
79
80 // 生成算式集合
81 public HashSet<String> makeFormulas() {
82 HashSet<String> set = new HashSet<String>();
83 while (set.size() < this.questionsNum) {
84 String formula = this.makeFormula();
85 set.add(formula);
86 }
87 return set;
88 }
89
90
91 // 比较运算优先级
92 public int compare(String operator1, String operator2) {
93 int res = 0;
94 switch (operator1) {
95 case "+":
96 case "-":
97 if (operator2.equals("+") || operator2.equals("-") || operator2.equals("*") || operator2.equals("/")) {
98 res = 1;
99 } else {
100 res = -1;
101 }
102 break;
103 case "*":
104 case "/":
105 if (operator2.equals("*") || operator2.equals("/")) {
106 res = 1;
107 } else {
108 res = -1;
109 }
110 break;
111 }
112 return res;
113 }
114
115
116 // 生成算式结果
117 public Fraction getAnswer(String formula) {
118
119 int length = 0;
120 String[] formulaArr = formula.split(" ");
121 String operators = "+-*/";
122 Stack<Fraction> opNumbers = new Stack<Fraction>();
123 Stack<String> opOperators = new Stack<String>();
124 opOperators.add("#");// 字符栈中存储个#号,防止栈空
125 while (length < formulaArr.length) {
126 String op = formulaArr[length++];
127 if (operators.indexOf(op) > -1) {// 若是运算符,判断优先级
128 String sign = opOperators.peek();
129 int priority = compare(op, sign);// 要入栈的跟栈顶的相比
130 if (priority >= 0) {// 如果要入栈的运算符高或者相等,出栈两个数字,和之前的运算符,计算后,将数字入栈,将字符入栈
131 opNumbers.add(compute(opOperators, opNumbers));
132 opOperators.add(op);
133 } else {// 入栈运算符优先级低,直接入栈
134 opOperators.add(op);
135 }
136 continue;
137 }
138 // 若是数字,则入栈
139 if (op.matches("\\d+/\\d+")) {
140 String[] strs = op.split("/");
141 int fenZi = Integer.parseInt(strs[0]);
142 int fenMu = Integer.parseInt(strs[1]);
143 opNumbers.add(new Fraction(fenZi, fenMu));
144 } else {
145 int fenZi = Integer.parseInt(op);
146 opNumbers.add(new Fraction(fenZi, 1));
147 }
148
149 }
150 while (opOperators.peek() != "#") {
151 opNumbers.add(compute(opOperators, opNumbers));
152 }
153 Fraction lastResult = null;
154 String resultArr = opNumbers.pop()+"";
155 if (resultArr.matches("-?\\d+/\\d+")) {
156 String[] strs2 = resultArr.split("/");
157 int lastFenZi = Integer.parseInt(strs2[0]);
158 int lastFenMu = Integer.parseInt(strs2[1]);
159 lastResult=changeFraction(lastFenZi,lastFenMu);
160
161 }
162 return lastResult;
163
164 }
165
166
167 //给分数约分
168 public Fraction changeFraction(int a,int b) {
169 if(a < 0) {
170 a = -a;
171 int min = a < b ? a : b;
172 for (int i = min;i >= 1;i --) {
173 if (a % i == 0 && b % i == 0) {
174 a=a/i;
175 b=b/i;
176 break;
177 }
178
179 }
180 return new Fraction(-a,b) ;
181 }
182
183 int min = a < b ? a : b;
184 for (int i = min;i >= 1;i --) {
185 if (a % i == 0 && b % i == 0) {
186 a=a/i;
187 b=b/i;
188 break;
189 }
190
191 }
192 return new Fraction(a,b) ;
193
194 }
195
196
197
198 // 算式求值
199 public Fraction compute(Stack<String> opOperators, Stack<Fraction> opNumbers) {
200 Fraction num2 = opNumbers.pop();
201 Fraction num1 = opNumbers.pop();
202 String _op = opOperators.pop();
203 Fraction result = null;
204 switch (_op) {
205 case "+":
206 result = num1.add(num2);
207 break;
208 case "-":
209 result = num1.sub(num2);
210 break;
211 case "*":
212 result = num1.multiply(num2);
213 break;
214 case "/":
215 result = num1.div(num2);
216 break;
217 }
218 return result;
219 }
220
221
222 // 生成算式结果数组
223 public Fraction[] getAnswers(HashSet<String> set) {
224 Fraction[] arr = new Fraction[set.size()];
225 int i = 0;
226 for (String str : set) {
227 arr[i++] = getAnswer(str);
228 }
229 return arr;
230 }
231
232 // 输出算式到文件
233 public String outputFormula(HashSet<String> set) {
234 File file = new File("Exercises.txt");
235 try {
236 int b = 1;
237 PrintStream ps1 = new PrintStream(file);
238 for (String str : set) {
239
240 ps1.println(b + ". " + str + "=");
241 b++;
242 }
243 ps1.close();
244 } catch (Exception e) {
245 System.out.println("Error" + e.getMessage());
246 System.exit(0);
247 }
248 return file.getAbsolutePath();
249 }
250
251 // 输出答案到文件
252 public String outputAnswers(Fraction[] arr) {
253 File file = new File("Answers.txt");
254 try {
255 PrintStream ps2 = new PrintStream(file);
256 for (int i = 0; i < arr.length; i++) {
257 ps2.print(i + 1 + ". ");
258 ps2.println(arr[i]);
259 }
260 ps2.close();
261 } catch (Exception e) {
262 System.out.println("Error" + e.getMessage());
263 System.exit(0);
264 }
265 return file.getAbsolutePath();
266 }
267
268 }

2.     Fraction  分数类,计算分数的加减乘除以及显示分数:

 1 package creater;
2
3 public class Fraction {
4
5 int fenzi;
6 int fenmu;
7
8 public Fraction(int fenzi, int fenmu) {
9 if (fenmu == 0) {
10 throw new IllegalArgumentException("分母不能为0");
11 }
12 this.fenzi = fenzi;
13 this.fenmu = fenmu;
14 }
15
16 // 分数的加法
17 public Fraction add(Fraction other) {
18 int fm = this.fenmu * other.fenmu;
19 int fz = this.fenzi * other.fenmu + other.fenzi * this.fenmu;
20 return new Fraction(fz, fm);
21 }
22
23 // 分数的减法
24 public Fraction sub(Fraction other) {
25 int fm = this.fenmu * other.fenmu;
26 int fz = this.fenzi * other.fenmu - other.fenzi * this.fenmu;
27 return new Fraction(fz, fm);
28 }
29
30 // 分数的乘法
31 public Fraction multiply(Fraction other) {
32 int fm = this.fenmu * other.fenmu;
33 int fz = this.fenzi * other.fenzi;
34 return new Fraction(fz, fm);
35 }
36
37 // 分数的除法
38 public Fraction div(Fraction other) {
39
40 int fm = this.fenmu * other.fenzi;
41 int fz = this.fenzi * other.fenmu;
42 return new Fraction(fz, fm);
43 }
44
45 // 分数的显示
46 public String toString() {
47
48
49
50 return fenzi + "/" + fenmu;
51 }
52
53
54 }
3.creater  类包含主方法,程序的开始。
 1 package creater;
2
3 import java.util.Scanner;
4
5 public class creater {
6
7 public interface Fraction {
8
9 }
10
11 public static void main(String[] args) {
12 // TODO 自动生成的方法存根
13 long startTime = System.currentTimeMillis();
14 Scanner choose = new Scanner(System.in);
15 System.out.println("************************************欢迎来到四则运算生成器******************************************");
16 System.out.println("请选择生成题目数量:");
17 int questionsNum = choose.nextInt();
18 System.out.println("请输入算术范围:");
19 int numRange = choose.nextInt();
20
21 new FormulaMaker(numRange, questionsNum);
22 System.out.println("题目文件生成完毕!");
23 long endTime = System.currentTimeMillis();
24 System.out.println("程序运行时间:" + (endTime - startTime) + "ms"); //输出程序运行时间
25 }
26
27 }

五:测试结果

结果一:测试结果比较小的时候(如生成20道题,算数在10以内)

控制台显示内容:

1.生成的算式文件--Exercises.txt

2.生成的答案文件--Answers.txt

结果二:程序能支持一万道题目的生成

控制台显示内容:

1.生成的算式文件--Exercises.txt

2.生成的答案文件--Answers.txt

六:项目小结

  本次的项目和上次相比有许多不同的地方,在项目完成后,做出以下结论:第一:这一次是两个人一同做一个项目,这样会比一个人单独做会简单一些。毕竟合作的作用就是1+1>2 。但是两个人合作也会有一些弊端,比如两个人的分工合作的调度是一个问题。第二:这是第二次的作业,明显的比上一次有了更多的做项目的经验,但是却发现了新的问题,就是编程知识的不足,这是项目经验弥补不了的,比如在大脑中构思好了某一个方法的流程和结构,但是总会在一些小细节上卡住,虽然说是小细节,但是影响也是巨大的。毕竟程序这种东西错了一个标点符号都是不可行的。第三:程序的方法之间会有紧密的联系,牵一发而动全身,因此后期的修改工作也是比较复杂。总而言之,提升自己的知识储备是当务之急!

项目作者:朱伟彬3117004639      商爱虎3117004626

结对编程(-java-实现)的更多相关文章

  1. 结对编程——Java实现黄金分割点游戏

    这是我和队员根据老师要求自创的一个人机黄金分割点游戏.这个小游戏在Windows10 下开发,用Eclipse做开发工具,实现语言是Java. 利用目前自己所学的Java知识实现了一人登录,电脑自行匹 ...

  2. 20175226 2018-2019-2《java程序设计》结对编程-四则运算(第一周-阶段总结)

    结对编程-四则运算(第一周-阶段总结) 需求分析 实现一个四则运算程序,要求: 自动随机生成小学四则运算题目(加,减,乘,除) 支持整数.真分数且支持多项式 能够利用栈的思想,将中缀转换为后缀表达式 ...

  3. 20175305张天钰Java结对编程四则运算(二)

    Java结对编程四则运算(二) 一.题目描述及要求 Git提交粒度不要太粗,建议一个文件/一个类/一个函数/一个功能/一个bug修复都进行提交,不能一天提交一次,更不能一周一次,参考Commit Me ...

  4. 20175305张天钰Java结对编程四则运算

    Java结对编程四则运算 一.题目描述:如何对表达式进行求值运算呢 1.中缀表达式与后缀表达式(娄老师讲解) 中缀表达式就是运算符号在运算数中间的表达式,比如1+2,顾名思义,后缀表达式就是运算符在运 ...

  5. 20175324王陈峤宇 2018-2019-2《Java程序设计》结对编程项目-四则运算 第一周 阶段性总结

    20175324王陈峤宇 2018-2019-2<Java程序设计>结对编程项目-四则运算 第一周 阶段性总结 需求分析 这次的结对作业是要求我们利用栈来设计一个计算器. 自动生成四则运算 ...

  6. 20175229许钰玮 2018-2019-2《Java程序设计》结对编程项目-四则运算 第一周 阶段性总结

    20175229许钰玮 2018-2019-2<Java程序设计>结对编程项目-四则运算 第一周 阶段性总结 需求分析 自动生成四则运算题目(加.减.乘.除). 既可以用前缀算法(波兰算法 ...

  7. 2017-2018-2 165X 『Java程序设计』课程 结对编程练习_四则运算

    2017-2018-2 165X 『Java程序设计』课程 结对编程练习_四则运算 经过第一阶段的学习,同学们已经熟悉了这门语言基本的用法.在一次又一次对着电脑编写并提交代码,进行练习的时候,有没有觉 ...

  8. 20175312 2018-2019-2 《Java程序设计》结对编程练习_四则运算(第二周:整体性总结)

    20175312 2018-2019-2 <Java程序设计>结对编程练习_四则运算(第二周:整体性总结) 结对对象与其博客链接 20175309 刘雨恒:https://www.cnbl ...

  9. 20175312 2018-2019-2 《Java程序设计》结对编程练习_四则运算(第一周:阶段性总结)

    20175312 2018-2019-2 <Java程序设计>结对编程练习_四则运算(第一周:阶段性总结) 结对对象与其博客链接 20175309 刘雨恒:https://www.cnbl ...

  10. JAVA结对编程--阶段总结

    一.需求分析 1.基本需求 随机生成n道题目 支持整数.分数,支持多运算符 能判断正误,错误时给出正确答案 能计算出正确率 2.扩展需求 处理生成题目并输出到文件 完成题目后从文件读入并判题 支持多语 ...

随机推荐

  1. rust 高级话题

    目录 rust高级话题 前言 零大小类型ZST 动态大小类型DST 正确的安装方法 结构体 复制和移动 特征对象 引用.生命周期.所有权 生命周期 错误处理 交叉编译 智能指针 闭包 动态分派和静态分 ...

  2. 网络爬虫之使用pyppeteer替代selenium完美绕过webdriver检测

    1引言 曾经使用模拟浏览器操作(selenium + webdriver)来写爬虫,但是稍微有点反爬的网站都会对selenium和webdriver进行识别,网站只需要在前端js添加一下判断脚本,很容 ...

  3. 四,专著研读(K-近邻算法)

    四,专著研读(K-近邻算法) K-近邻算法有监督学习距离类模型, k-近邻算法步骤 计算已知类别数据集中的点与当前点之间的距离 按照距离递增的次序进行排序 选取与当前点距离最小的K个点 确定前k个点出 ...

  4. day74_10_21 三大认证

    一.权限六表. 一般在django中,基于用户权限访问控制的认证是RBAC(Role-Based Access Control) 还有一些基于auth的认证规则. Django框架采用的是RBAC认证 ...

  5. 【Eureka篇三】Eureka服务发现(4)

    注:该知识点并不是重点. 修改子模块:microservicecloud-provider-dept-8001 1. 修改DeptController @Autowired private org.s ...

  6. MySQL学习笔记5——编码

    MySQL学习笔记5之编码 编码 1.查看MySQL数据库编码 *SHOW VARIABLES LIK 'char%'; 2.编码解释 *character_set_client:MySQL使用该编码 ...

  7. URL、URI、URN之间的区别

    URL统一资源定位符 URI统一资源标识符 URN统一资源名称 URL是URI的一个特例. URI由URL和URN两部分组成. 在java类中,URI类不包含任何访问资源的方法,它唯一的作用就是解析. ...

  8. ASP.NET开发实战——(十一)ASP.NET MVC 与数据库之EntityFramework配置与连接字符串

    前几篇文章中介绍了如何使用Entity Framework来操作数据库,但是对EF的配置.连接字符串的指定仍然存在一些疑问,EF可以通过两种方式来实现配置,分别是代码方式和配置文件. 本章将通过以下几 ...

  9. k8s二进制部署

    k8s二进制部署 1.环境准备 主机名 ip地址 角色 k8s-master01 10.0.0.10 master k8s-master02 10.0.0.11 master k8s-node01 1 ...

  10. 多维度对比5款主流分布式MQ消息队列,妈妈再也不担心我的技术选型了

    1.引言 对于即时通讯网来说,所有的技术文章和资料都在围绕即时通讯这个技术方向进行整理和分享,这一次也不例外.对于即时通讯系统(包括IM.消息推送系统等)来说,MQ消息中件间是非常常见的基础软件,但市 ...