zoukankan      html  css  js  c++  java
  • 20175126Apollo 20175126《Java程序设计》结队编程项目——四则运算

    结队编程项目——四则运算

     

    一、项目需求

    • 自动生成小学四则运算题目(加、减、乘、除)统计正确率
      • 支持整数
      • 支持多运算符(比如生成包含100个运算符的题目)
      • 支持真分数

    需求分析:

    生成四则运算:需要使用随机数生成,需要创造一个能实现计算功能的类。

    支持多运算符:运算符也需要利用随机生成,并且不限个数。

    支持真分数:需要用到生成分子、分母的函数,将分数化简等。

    统计正确率:需要设置一个计算变量,并需要用一个判断正确的函数。

     

    二、设计思路

    首先根据需求分析,进行大体的设计:

    生成题目→输入答案→判断正误→下一道题→生成题目→ ......→显示正确率

    我和搭档决定一共用四个类,来完成本次项目:1.Main.java   2.栈.java  3.基本运算计算.java  4.栈内运算.java

    UML类图:

     

    三、关键代码

    压栈\出栈:

    第一周我们打算先完成栈和计算的部分,根据老师发的参考网站,我们又自行百度了很多关于栈的学习资料...但由于我们的水平有限,经过一下午的时间,还是未能完全搞懂如何利用栈来进行后缀计算,所以我们向学长请教,在学长的指导下,完成了部分代码。我们的栈主要分为两个部分,一是DataStack,专门用来存储数字,二是CharStack用来存储运算符。

    public class CharStack {
    	int n;
    	char [] a;
    	int top = -1;
    	public CharStack(int m) { //定义栈的大小
    		this.n=m;
    	}
    	void getStack() { // 定义栈的大小
    		a = new char[n];
    	}
    	void push(char data) {  //压栈
    		a[++top]=data;
    	}
    	char pop() {//出栈
    		return a[top--];
    	}
    	
    }
    

      

    public class DataStack { //代码原理同上一个CharStack
    	int n;
    	Rational [] a;
    	int top = -1;
    	public DataStack(int m) { 
    		this.n=m;
    	}
    	void getStack() {
    		a = new Rational[n];
    		for(int i=0;i<n;i++) {
    			a[i] = new Rational();
    		}
    	}
    	void push(Rational data) {
    		top++;
    		a[top].numerator=data.numerator;
    		a[top].denominator=data.denominator;
    	}
    	Rational pop() {
    		return a[top--];
    	}
    }
    

      

    题目运算:

    而计算部分我们则采取了全分数计算的方式,整数也作为分母为1的分数。并且还能做到对分数进行约分,我们想的是利用找分子分母最大公约数,然后同除以其约数,完成约分。在将运算共分为四种情况:加减乘除。先利用分子分母有理化,将分母化为一样的,然后再进行基本运算,得到新的分数,再进行约分,得到答案。

       void setNumerator(double a) {  //设置分子
          double c=f(Math.abs(a),denominator);  //计算最大公约数
          numerator = a/c;//约分
          denominator = denominator/c;
          if(numerator<0&&denominator<0) { //分子分母负数情况
              numerator = -numerator;
              denominator = -denominator;
          }
       }
       void setDenominator(double b) {  //设置分母
          double c=f(numerator,Math.abs(b));  //计算最大公约数
          numerator = numerator/c;
          denominator = b/c;
          if(numerator<0&&denominator<0) {
              numerator = -numerator;
              denominator = -denominator;
          }
       }
       double getNumerator() {//返回分子
          return numerator;
       }
       double getDenominator() {
         return denominator;
       }  
       double f(double a,double b) { //求a和b的最大公约数
          if(a==0) return 1;
          if(a<b) {
             double c=a;
             a=b;
             b=c; 
          }
          double r=a%b;
          while(r!=0) { //辗转相除
             a=b;
             b=r;
             r=a%b;
          } 
          return b;
       }
    

     

    栈内运算:

    这一部分我们主要思路是:将生成的运算表达式的字符串转换为double型然后进行调用题目运算的部分进行栈内运算,并且将具体的数字压栈出栈运算都放在了这里进行。这一部分主要参考与博客《调度场的运算》:http://hczhcz.github.io/2014/02/27/shunting-yard-algorithm.htm。虽然说完成这个功能的代码比较繁琐,但是最终还是能够达到预期效果。

    	Rational manage() {
    		int i=0;
    		Rational r = new Rational();
    		double d;
    		while(true) {
    			if(i>=a.length())
    				break;
    			char c = a.charAt(i); //看第i处的内容
    			if(c>='0' && c<='9') {//从字符串中检测数字
    				String temp = String.valueOf(c);
    				String s = new String();
    				s = s+temp;
    				i++;
    				if(i>=a.length()) {
    					d = Double.parseDouble(s); //将字符串转换为double型
    					r.setNumerator(d);
    					datastack.push(r);
    					break;
    				}
    				c = a.charAt(i);
    				while(c>='0' && c<='9') {
    					temp = String.valueOf(c);
    					s = s+temp;
    					i++;
    					if(i>=a.length())
    						break;
    					c = a.charAt(i);
    				}
    				d = Double.parseDouble(s);
    				r.setNumerator(d);
    				datastack.push(r);
    				continue;
    			}
    			else if(c=='*' || c=='/') {//从字符串中检测运算符
    				while(true) {
    					if(charstack.top==-1) {//如果符号栈顶无元素,入栈。
    						charstack.push(c);
    						break;
    					}
    					if(charstack.a[charstack.top]=='+' || charstack.a[charstack.top]=='-') {//如果符号栈顶是+或-,入栈。
    						charstack.push(c);
    						break;
    					}
    					else if((charstack.a[charstack.top]=='*' || charstack.a[charstack.top]=='/') && (datastack.top>=1)) {//如果符号栈顶是*或/,并且栈内元素大于等于1,计算。
    						calculate(charstack.a[charstack.top]);
    						continue;
    					}
    					else {
    						charstack.push(c);
    						break;
    					}
    				}
    			}
    			else if(c=='+' || c=='-') {
    				while(true) {
    					if(charstack.top==-1) {//如果符号栈顶无元素,入栈。
    						charstack.push(c);
    						break;
    					}						
    					else if((charstack.a[charstack.top]=='+' || charstack.a[charstack.top]=='-' || charstack.a[charstack.top]=='*' || charstack.a[charstack.top]=='/') && (datastack.top>=1)) {
    						calculate(charstack.a[charstack.top]);//计算。
    						continue;
    					}
    					else {
    						charstack.push(c);
    						break;
    					}
    				}
    				
    			}
    			else if(c=='(') {//如果符号是(,入栈。
    				charstack.push(c);
    			}
    			else if(c==')') {//如果符号是),栈内符号依次计算。
    				while(true) {
    					if(charstack.a[charstack.top]=='(') {
    						charstack.pop();
    						break;
    					}
    					else {
    						calculate(charstack.a[charstack.top]);
    					}
    				}
    			}
    			i++;
    		}
    		while(true) {
    			if(datastack.top>=1)
    				calculate(charstack.a[charstack.top]);
    			else
    				break;
    		}
    		return datastack.pop();
    	}
    

     程序效果图:

    四、遇到的困难及解决办法

    问题1:不会栈的使用

    问题1解决办法:参考网上的博客:《栈详解及Java实现》 https://www.cnblogs.com/fzz9/p/8167546.html,然后对于一些细节不懂的地方再请教学长

    问题2:没有分数运算的思路,无从下手

    问题2解决办法:参考网上的博客:《Java-分数运算》https://blog.csdn.net/slyslyme/article/details/80032526。

     

    五、对小伙伴鑫浩的评价:

    搭档是一个非常有责任心的伙伴,也是一个很热情的人,在我们开发项目之前,他就已经进行了一些关于项目所需函数的了解,并且在设计时他也非常积极,在共同工作时总能给与我很大的帮助。

    六、P2P图

    PSP2.1Personal Software Process Stages预估耗时(分钟)实际耗时(分钟)
    Planning 计划 20  20
    · Estimate · 估计这个任务需要多少时间 30  30
    Development 开发 300  200
    · Analysis · 需求分析 (包括学习新技术) 300   350
    · Design Spec · 生成设计文档 30   30
    · Design Review · 设计复审 (和同事审核设计文档) 30   30
    · Coding Standard · 代码规范 (为目前的开发制定合适的规范) 30   30
    · Design · 具体设计 180   90
    · Coding · 具体编码 400  120
    · Code Review · 代码复审 180  40
    · Test · 测试(自我测试,修改代码,提交修改) 30  40 
    Reporting 报告 90  60 
    · Test Report · 测试报告 90   60
    · Size Measurement · 计算工作量 90  20 
    · Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 90  40 
      合计 1890 900 
  • 相关阅读:
    WayOs 聊天软件号码全自动登陆查询系统,支持号码复制、消息发送、号码导出
    easyradius中,如何把wayos中的数据同步到easyradiu中?
    EPON、GPON无源光网络在城中村、小区网络中的解决方案
    EasyRadius 从1.6升级到 1.65 提示:初始化连接失败,未找到可用的接口信息,解决方案
    WayOs 计费 EasyRadius宽带云计费系统隆重发布,支持一个帐号管理多个路由的
    故障处理:这几天发现的几个WAYOS故障问题的现象及分析,解决方案
    Delphi内嵌汇编语言BASM精要(转帖)
    Windows SDK编程(Delphi版) 之 消息处理
    E销助手软件
    Delphi与Python结合
  • 原文地址:https://www.cnblogs.com/apollooo/p/10645536.html
Copyright © 2011-2022 走看看