四则运算项目报告
代码仓库地址:https://dev.tencent.com/u/dingj2333/p/sizeyunsuan/git
一、需求分析:
- 程序可接收一个输入参数n,然后随机产生n道加减乘除(分别使用符号“+,-,*,÷”来表示)练习题,每个数字在 0 和 100 之间,运算符在3个到5个之间,并将结果输出到"result.txt"文件中;
- 每个练习题至少要包含2种运算符。同时在运算过程中不得出现负数与非整数,比如不能出 3÷5+2=2.6,2-5+10=7等算式;
- 支持有括号的运算式,且算式中存在的括号数必须大于2对,且不得超过运算符的个数;
- 支持真分数的出题与运算,且需支持运算时分数的自动化简,保证结果为真分数。
二、功能设计:
- 程序接收参数输入,并判断输入是否合法,如有不合法就提醒异常;
- 根据输入的参数输出相应数量的运算式并求解,有整数运算、分数运算以及对括号的考虑;
- 对整数进行运算时考虑优先级,对分数运算时考虑化简。
三、设计实现:
- Main类,程序的入口,里面有main方法,对输入做出判断并选择调用的类中的方法;
- Fraction 类、Zhengshu类、util类,在里面定义所用到的方法。
四、项目详情:
1.项目结构:
2.主函数:
import java.io.IOException;
import java.io.PrintStream;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
int number = 0;
Scanner s = new Scanner(System.in);
System.out.println("请输入要生成四则运算式的个数(1~100):");
number = s.nextInt();//从操作台输入运算式的个数
try {
//number = Integer.parseInt(args[0]);// 直接在命令行输入参数,且保证是[1-100]的整数
if (number <= 0)//若为负数则报错
System.out.println("输入数值不符,请输入正整数作为参数!");
if (number > 100)//若大于100则报错
System.out.println("输入数值不符,请输入不大于100的正整数作为参数!");
} catch (Exception e) {
System.out.println("输入数值不符,请输入[1,100]的整数作为参数!");
}
try {
PrintStream ps = new PrintStream("../result.txt");// 在根目录下生成测试文件
System.setOut(ps);
} catch (Exception e) {
System.out.println("生成文件失败");
}
System.out.println("2017012237");
for (int i = 0; i < number; i++) {
int choose = (int) (Math.random() * 100);//选择进行整数还是分数运算
if (choose <= 60 && choose >= 0)
Zhengshu.zhengshu(1);
else
Fraction.fraction(1);
}
}
}
3.整数运算:
...
...
if (opt[type] == '-') { //减法运算
while (s1 < s2) { //如果被减数小于减数,不合法,则重新生成随机数
s1 = (int) (Math.random() * 100);
s2 = (int) (Math.random() * 100);
}
sum = s1 - s2;//保证减法合法
}
...
...
if (opt[typ] == '-') {
while (sum < s) {//保证结果不能为负数
s = (int) (Math.random() * 100);
}
sum = sum - s;
}
...
if (opt[typ] == '÷') {
while (s == 0 || sum % s != 0) {//保证除法运算合法且能整除
s = (int) (Math.random() * 100 + 1);
}
sum = sum / s;
}
...
} else { //优先级用括号来判别
if (opt[typ] == '*')
sum = sum * s;
if (opt[typ] == '÷') {
while (s == 0 || sum % s != 0) {
s = (int) (Math.random() * 100 + 1);
}
sum = sum / s;
...
4.分数运算:
...
...
while (fenz1 >= fenm1) // 处理分子大于分母
fenm1 = (int) (Math.random() * 20 + 1); // 重新生成分母
int div1 = util.gcd(fenm1, fenz1);//将分数最简化,除最大公约数
...
...
if (fenm1 == fenm2)// 分母相等的情况
{
fenm = fenm1;
if (type == 0)
{
fenz = fenz1 + fenz2;
if (fenz >= fenm)// 过程大于1,重新生成分式
j--;
else {
int div = util.gcd(fenm, fenz);
fenz /= div;
fenm /= div;
...
} else//分母不等的情况
{
fenz = fenz1 - fenz2;
if (fenz <= 0)// 保证过程非负
j--;
else {
int div = util.gcd(fenm, fenz);
fenz /= div;
fenm /= div;
...
}
} else {
fenm = fenm1 * fenm2;
if (type == 0) {
fenz = fenz1 * fenm2 + fenz2 * fenm1;
if (fenz >= fenm)
j--;
else {
int div = util.gcd(fenm, fenz);
fenz /= div;
fenm /= div;
...
...
} else {
fenz = fenz1 * fenm2 - fenz2 * fenm1;
if (fenz <= 0)//保证过程非负
j--;
else {
int div = util.gcd(fenm, fenz);
fenz /= div;
fenm /= div;
...
...
5.优先级和最大公约数:
//判断优先级的函数,加括号有意义
public class util {
public static int youxianji(char c) {
if (c == '*' || c == '÷')
return 3;
if (c == '+' || c == '-')
return 2;
if (c == '(')
return 1;
return 0;
}
//最大公因数的函数,使分数最简
public static int gcd(int x, int y) {
int z = y;
while(x%y!=0)
{
z = x%y;
x = y;
y = z;
}
return z;
}
}
6.运行结果:
五、PSP展示:
任务内容 |
计划共完成需要的时间(min) |
实际完成需要的时间(min) |
计划 |
15 |
30 |
估计这个任务需要多少时间,并规划大致工作步骤 |
15 |
30 |
开发 |
1000 |
4000 |
需求分析 (包括学习新技术) |
120 |
240 |
生成设计文档 |
30 |
50 |
设计复审 (和同事审核设计文档) |
30 |
180 |
代码规范 (为目前的开发制定合适的规范) |
30 |
60 |
具体设计 |
30 |
60 |
具体编码 |
710 |
3210 |
代码复审 |
20 |
50 |
测试(自我测试,修改代码,提交修改) |
30 |
50 |
报告 |
25 |
50 |
测试报告 |
10 |
20 |
计算工作量 |
5 |
10 |
事后总结, 并提出过程改进计划 |
10 |
20 |
六、总结反思:
通过这次项目的实现过程,我清楚的认识到了自己在代码这方面的不足,在做项目的时候遇到很多问题还要去不停的查书找资料,以至于浪费很多时间,而且这次的项目一开始并不想去实现附加功能,觉得自己会做不出来,但是在参考一些学长学姐的代码后,还是决定写一写,最后还是按照别人的思路完成了项目。所以我觉得在以后的学习中我要更加努力,练习独立思考的能力,自己多去尝试,期待以后的表现吧……