仓库地址:https://git.coding.net/lzgy18/second_work.git
- 需求分析 :
大概:做一个用Java语言随机产生四则运算的题目及其结果
输入:输入n,代表共产生n道题,n必须为整数
过程:随机产生三到四个运算符,以及运算数,产生运算表达式,并且计算出结果(难点:运算符的优先级计算)
注意:除法运算时应注意除数为零的情况,以及除不尽的情况
减法运算时,不能出现负数。
且一个式子中至少出现两种运算符
输出:输出n 道四则运算的题目及其结果,并且将其传送到指定文件中
2.功能设计
(1)基本功能
输入练习题的个数,并判断是否为整数,是否合理
建立运算符的数组,利用random方法产生随机数
产生练习题的表达式(将其转化为后缀表达式)
利用栈设计运算符的优先级并计算练习题的结果
将结果输出到指定文件中,并输入学号
(2)附加功能
支持有括号的运算式,包括出题与求解正确答案。
3.设计实现(设计包括你会有哪些类,这些类分别负责什么功能,他们之间的关系怎样?你会设计哪些重要的函数,关键的函数是否需要画出流程图?函数之间的逻辑关系如何?)
(1)Main.java:主要用于生成四则运算的练习题,并调用ArrayPractice类和Writting类
(2)ArrayPractice:用于计算表达式的结果,其中有包括中缀表达式转后缀表达式的方法,以及处理运算符优先级的方法。
(3)Writting:用于将结果集,根据路径存放到指定文件中
4.算法详解
生成题目:主要用到random方法产生随机数,通过for循环,利用数组,重组运算符和运算数,其中利用递归算法解决了负数问题和分数问题,以及至少出现两个运算符。
解答题目:重建一类解决计算结果的问题,首先处理生成的表达式,判断其是运算符还是运算时,并一起存放于list集合中
然后通过栈来决定运算符的优先级,将中缀表达式转化为后缀表达式,
“+”“-”属于同一级,“*”“/”属于同一级,
利用栈,遇到数字输出,遇到高优先级的全部出栈,最后在全部出栈,生成后缀表达式,进而进行计算。
5.测试运行
(1)运行结果
(2)主方法
(3)charge1方法和needing方法(解决分数,负数,以及生产表达式及其结果)
(4)Writting类
(5)ArrayPractice类
6.粘贴自己觉得比较独特的或满意的代码片段,用博客园正确的代码控件来显示。
private static int charge1(int x,int y) {//解决分数问题 if(y==0) {//如果除数为0,则重新产生 y=(int) (Math.random()*100); return charge1(x,y); } if(x%y!=0) {//如果除不尽,利用递归重新产生数 y=(int) (Math.random()*100); return charge1(x,y); } else { return y; } }
if(s.equals("+")){ int a1 = stack.pop(); int a2 = stack.pop(); int v = a2+a1; stack.push(v); }else if(s.equals("-")){ 当减值为负数时,return -1,回到main.java,利用递归,重新产生数 int a1 = stack.pop(); int a2 = stack.pop(); int v = a2-a1; if(v<0) return -1; else stack.push(v); }else if(s.equals("*")){ int a1 = stack.pop(); int a2 = stack.pop(); int v = a2*a1; stack.push(v); }else if(s.equals("/")){ int a1 = stack.pop(); int a2 = stack.pop(); int v = a2/a1; if(a2<a1){ return -1;当被除数小于除数时,return -1,回到main.java,利用递归,重新产生数
} else stack.push(v); } }
static ScriptEngine js= new ScriptEngineManager().getEngineByName("JavaScript"); private static ArrayListresult(ArrayList arrayList){ ArrayList a=new ArrayList (); for(String al:arrayList){ 刚开始用的是js的eval方法直接将表达式转换并且计算,但是发现这个解决负数问题以及分数问题比较困难
,虽然不需要涉及到运算符的优先级,所以摈弃了这个方法,但是我觉得这个方法还是比较好用的 try { al=al+"="+js.eval(al); System.out.println(al); a.add(al); } catch (ScriptException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return a; }
private static int same(int i,int b[]){//至少出现两种运算符 Random r=new Random(); if(b[i]==b[i-1]){ b[i]= r.nextInt(4); return same(i,b); } return b[i]; }
7. 总结:你设计的程序如何实现软件设计的'模块化'原则。
在main类中,将各种要求用不同的方法实现,然后再用主方法调用,在其他类中也是,好管理代码,容易修改,不会使代码显得冗余
8. 展示PSP
PSP2.1 |
任务内容 |
计划共完成需要的时间(h) |
实际完成需要的时间(h) |
· Estimate |
· 估计这个任务需要多少时间,并规划大致工作步骤 |
37 |
43 |
Development |
开发 |
37 |
43 |
· Analysis |
· 需求分析 (包括学习新技术) |
5 |
7 |
· Design Review |
· 设计复审 (和同事审核设计文档) |
2 |
3 |
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
4 |
7 |
· Design |
· 具体设计 |
4 |
7 |
· Coding |
· 具体编码 |
12 |
16 |
· Code Review |
· 代码复审 |
5 |
8 |
· Test |
· 测试(自我测试,修改代码,提交修改) |
2 |
5 |
· Size Measurement |
· 计算工作量 |
1 |
1 |
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
3 |
7 |
感言
(1) 在实现这个四则运算的过程中,遇到了很多阻碍,在经过一段时间的努力,可以写出随机产生四则运算的公式,但难点就在于怎样去计算这个公式的结 果,最开始,我用的是js中的eval,只需要写一个方法,就可以得到结果,自己也不需要知道,到底是怎样的一个算法,以及过程。刚开始还挺高兴的,但后来发现,用这个方法我不会解决负数的问题一分数的问题。
(2) 再后来,我就写了一个方法,对于减法运算使得前一个数不许小于后一个数,听起来是对的,但对于23-12*2,其结果就是负的,所以不够全面,本来是想找一个不需要用到栈就可以解决运算符优先级的方法,但就是没找到,只能怪自己太才疏学浅了。
(3)然后,我就找书,看博客,看了一下栈的基本操作,中缀怎样转后缀(只怪数据结构学的不精呀),过程着实艰难啊,不过这也是一个充实自己的算法的好机会。终于把算法写出来,但也还是会有一些小bug,不断地修修改改,最终代码形成了,最后全部都通过的时候真的特别开心,这是一个很好的锻炼机会,补缺了自己以前的一点漏洞,所以,我觉得,难不可怕,可怕的是自己一开始就逃避,不敢尝试。加油吧。
(4)还有一个就是命令行的测试,以前一直是在控制台测试,jdk的配置也不同,在命令行测试时就会出问题,然后就把jdk重新配置了一下,才算解决,还有中文乱码的问题,需要加入encoding utf-8 解决,在此过程中自己真的学到了很多。