一.【Coding.net原码仓库地址】https://git.coding.net/SccottZZ/Arithmetic.git
二.【软件需求分析】
1.编写JAVA程序可接收一个输入参数n,然后随机产生n道加减乘除(分别使用符号+-*÷来表示)练习题,每个数字在 0 和 100 之间,运算符在3个到5个之间。
2.为了让小学生得到充分锻炼,每个练习题至少要包含2种运算符。同时,由于小学生没有分数与负数的概念,所出的练习题在运算过程中不得出现负数与非整数,比如不能出 3÷5+2=2.6,2-5+10=7等算式。
3.练习题生成好后,将学号与生成的n道练习题及其对应的正确答案输出到文件“result.txt”中,不要输出额外信息,文件目录与程序目录一致。
4.当程序接收的参数为4时,以下为一个输出文件示例。
2018010203
13+17-1=29
11*15-5=160
3+10+4-16=1
15÷5+3-2=4
附加需求
1.产生带括号的四则运算并求解,算式中存在的括号必须大于2个,且不得超过运算符的个数。
2.产生真分数的加减法运算,运算过程中都为最简真分数。
三.【功能设计】
1.实现了四则运算,并将算式与计算结果写入指定文件;
2.至少要包含2种运算符,用排除了出现负数与非整数的情况;
3.完成了提示命令行测试
四.【算法思路】
Lib中自定义函数,NumCreate(int n )和OperateCreate(int n)生成一个算式的2-5个随机运算数和1-4个运算符,在AriCreate(int n )中调用前两个方法生成一个完整算式和正确答案,并将“/”替换为“÷”,将“*”替换为“×”,并判断结果正负和是否为小数,否则重新生成。
import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.LinkedList; import java.util.Random; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; public class Lib { static ScriptEngine je = new ScriptEngineManager().getEngineByName("JavaScript"); //字符串转换成算术表达式并计算 //生成一个算式的2-4个随机运算数 public int[] NumCreate(int n ){ //生成1000以内的随机数,放入num[]数组中 int num[] = new int[n]; for(int m = 0 ;m < n ;m++){ num[m] = (int) (Math.random()*100 + 1); } return num; } public char[] OperateCreate(int n){ //result[i]存放计算结果 char[] c= {'+','-','*','/'}; //一个算式生成n-1个运算符,存入operate【】中 char operate[] = new char[n-1]; for(int m = 0 ;m < n-1 ;m++){ int i = (int) (Math.random()*4); operate[m] = c[i]; } return operate; } //生成算式 String AriCreate(int n ) throws ScriptException{ while(true){ Lib arith = new Lib(); int num[] = arith.NumCreate(n); char operate[] = arith.OperateCreate(n); String ar = "" + num[n-1]; for(int i = 1 ;i < n ; i++){ ar = ar + operate[i-1] + num[i-1]; } try{ String result= "" + je.eval(ar) ; double d = Double.parseDouble(result); //判断结果正负和是否为小数,否则重新生成 if(d>=0&&(d-(int)d ==0)){ //将“/”替换为“÷”,将“*”替换为“×”,用正则表达式去掉小数 result = ar.replaceAll("\*","×").replaceAll("/","÷") + "=" + result.replaceAll("0+?$","").replaceAll("[.]$",""); return result; } } catch (ScriptException e) { e.printStackTrace(); } } } }
Mian.java中通过for循环生成算式组,通过提示命令行输入args[0],键入所需的算式个数,并写入指定文件。
import java.lang.*; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.Scanner; public class Main { public static void main(String[] args) throws IOException { @SuppressWarnings("resource") File f = new File("result.txt"); Lib lib = new Lib(); BufferedWriter bw = new BufferedWriter(new FileWriter(f)); //输出学号 bw.write("2016012083"); int n = 0; String temp; try{ for(int i = 0 ;i<Integer.parseInt(args[0]) ;i++){ //决定算式的运算数多少3-6 n=(int) (Math.random()*3 + 3); System.out.println(lib.AriCreate(n)); bw.newLine(); temp = lib.AriCreate(n); System.out.println(temp); bw.write(temp); } bw.close(); }catch(Exception e){ System.out.println(e); } } }
五.【测试运行】
注:为了显示出效果,在控制台也设置了输出,实际ecoding中提交的代码并没有设置
src目录结构
六.【PSP数据】
PSP | 任务内容 | 计划共完成需要的时间(min) | 实际完成需要的时间(min) |
Planning | 计划 | 8 | 10 |
Estimate | 估计每个阶段的时间成本,并规划大致工作步骤 | 8 | 10 |
Development | 开发 | 710 | 735 |
Analysis | 需求分析 (包括学习新技术) | 60 | 60 |
Design Spec | 生成设计文档 | 40 | 50 |
Design Review | 设计复审 (和同事审核设计文档) | 40 | 45 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 30 | 40 |
Design | 具体设计 | 120 | 100 |
Coding | 具体编码 | 180 | 200 |
Code Review | 代码复审 | 150 | 150 |
Test | 测试(自我测试,修改代码,提交修改) | 90 | 90 |
Reporting | 报告 | 200 | 230 |
Test Report | 测试报告 | 120 | 150 |
Size Measurement | 计算工作量 | 20 | 20 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 60 | 60 |
七.【个人总结】
这次的代码最难的部分在于算法思路和平时的积累是否到位,对于我来说是一次挑战,“经此一役”也让我体会到了这门专业的严谨性与灵活性,也许有时只是一点点的小问题就会造成全项目的崩溃,一点点修改却又不能急躁,不然只会犯更多错。测试检查过程需要灵活,用测试代码分段查错更容易查出。
【4月12日修改补充】