java实现四则运算程序
github传送门:https://github.com/JJYdesu/operation
成员:赖展飞 江家懿
一、项目要求
实现一个自动生成小学四则运算题目的命令行程序。(实现)
1. 使用 -n 参数控制生成题目的个数。(实现)
2. 使用 -r 参数控制题目中数值(自然数、真分数和真分数分母)的范围。(实现)
3. 生成的题目中计算过程不能产生负数,也就是说算术表达式中如果存在形如e1 − e2的子表达式,那么e1 ≥ e2。(实现)
4. 生成的题目中如果存在形如e1 ÷ e2的子表达式,那么其结果应是真分数。(实现)
5. 每道题目中出现的运算符个数不超过3个。(实现)
6. 任何两道题目不能通过有限次交换+和×左右的算术表达式变换为同一道题目。(实现)
7、生成的题目存入执行程序的当前目录下的Exercises.txt文件,计算答案并存入执行程序的当前目录下的Answers.txt文件。(实现)
二、PSP
|
PSP2.1 |
Personal Software Process Stages |
预估耗时(分钟) |
实际耗时(分钟) |
|
Planning |
计划 |
30 |
50 |
|
· Estimate |
· 估计这个任务需要多少时间 |
30 |
50 |
|
Development |
开发 |
1450 |
1430 |
|
· Analysis |
· 需求分析 (包括学习新技术) |
60 |
50 |
|
· Design Spec |
· 生成设计文档 |
30 |
20 |
|
· Design Review |
· 设计复审 (和同事审核设计文档) |
30 |
30 |
|
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
30 |
30 |
|
· Design |
· 具体设计 |
100 |
100 |
|
· Coding |
· 具体编码 |
1000 |
1200 |
|
· Code Review |
· 代码复审 |
100 |
100 |
|
· Test |
· 测试(自我测试,修改代码,提交修改) |
100 |
100 |
|
Reporting |
报告 |
130 |
120 |
|
· Test Report |
· 测试报告 |
50 |
60 |
|
· Size Measurement |
· 计算工作量 |
50 |
30 |
|
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
30 |
30 |
|
合计 |
|
1610 |
1600 |
三、设计说明

- Formula类包含各种运算方法
- Create类调用Formula类中的方法生成式子
- Output类调用Create类打印式子,调用Formula类计算答案,将题目与答案存储到文件中
四、关键代码
Formula类
package formula;
import java.util.ArrayList; public class Formula { public static enum Operators { ADD, // 加 SUB, // 减 MUL, // 乘 DIV // 除 } public Operators operator = Operators.ADD; // 实际运算符,用于运算。 public int integer = 0; // 整数部分 public int numerator = 0; // 分子 public int denominator = 1; // 分母 public int symbol = 1; // 代表正负 public ArrayList<Formula> list; // 多项式 /** * 初始化空单项式 */ public Formula() { list = null; } /** * 初始化单项式 */ public Formula(Operators operator) { this.operator = operator; list = null; } /** * 生成自然数单项式 * @param operator 运算符 * @param integer 整数部分 */ public Formula(Operators operator, int integer){ this.operator = operator; if(integer > 0){ this.integer = integer; }else { this.integer = -1 * integer; this.symbol = -1; } list = null; } /** * 生成分数单项式 * @param operator * @param numerator * @param denominator */ public Formula(Operators operator, int numerator, int denominator){ this.operator = operator; this.integer = numerator / denominator; if(numerator * denominator < 0) { // 整数部分 this.symbol = -1; // 数值正负 this.integer = -1 * this.integer; // 正化 } numerator = numerator % denominator; // 求余 numerator = numerator < 0 ? -1 * numerator: numerator; // 正化 denominator = denominator < 0 ? -1 * denominator: denominator; // 正化 if(numerator > 0){ // 约分 int a, b, c; a = denominator; b = numerator; while ((c = a % b) != 0){ a = b; b = c; } this.numerator = numerator / b; this.denominator = denominator / b; } list = null; } /** * 生成单项式 * @param operator 运算符 * @param integer 整数部分 * @param numerator 分子 * @param denominator 分母 */ public Formula(Operators operator, int integer, int numerator, int denominator){ this.operator = operator; if(denominator < 0){ denominator = -1 * denominator; numerator = -1 * numerator; } numerator = integer * denominator + numerator; this.integer = numerator / denominator; if(numerator * denominator < 0) { // 整数部分 this.symbol = -1; // 数值正负 this.integer = -1 * this.integer; // 正化 } numerator = numerator % denominator; // 求余 numerator = numerator < 0 ? -1 * numerator: numerator; // 正化 denominator = denominator < 0 ? -1 * denominator: denominator; // 正化 if(numerator > 0){ // 约分 int a, b, c; a = denominator; b = numerator; while ((c = a % b) != 0){ a = b; b = c; } this.numerator = numerator / b; this.denominator = denominator / b; } list = null; } /** * 生成多项式 * @param operator * @param list */ public Formula(Operators operator, ArrayList<Formula> list){ this.operator = operator; this.list = list; this.injectFormulaValue(); } /** * 无打印 * @return 返回式子字符串 */ public String _print(){ String str = ""; if(list == null || list.size() == 0) { // 单项式 if(numerator > 0 && denominator > 0) str = numerator + "/" + denominator; if(integer > 0) { if(str != "") str = integer + "'" + str; else str = integer + ""; } if(str == "") str = "0"; else if(symbol == -1) str += "( - "+ str +")"; } else { // 多项式 int length = list.size(); for(int i = 0; i < length; i++){ Formula item = list.get(i); if(i == 0) { // 首项 if(item.operator == Operators.SUB) str += " - "; }else { switch (item.operator){ case SUB: str += " - ";break; case ADD: str += " + ";break; case MUL: str += " * ";break; case DIV: str += " ÷ ";break; } } if(item.list != null && item.list.size() > 1) str += '('+ item._print() +')'; else str += item._print(); } } return str; } /** * 控制台输出式子 * @return 式子字符串 */ public String print(){ String str = this._print() + " = "; System.out.println(str); return str; } /** * 记录式子数值 * @param */ public void injectFormulaValue(){ if(list == null) return; int length = list.size(), start = 0, end = 0; if(length < 1) return; // 计算式子值 Formula a, b, c = null; a = new Formula(); for(int i = 0; i < length; i++){ b = list.get(i); if(b.operator == Operators.DIV || b.operator == Operators.MUL){ a = this.mergeValue(a, b); }else { if(c == null) c = a; else c = mergeValue(c, a); a = b; } } c = mergeValue(c, a); // 记录值 this.integer = c.integer; this.numerator = c.numerator; this.denominator = c.denominator; this.symbol = c.symbol; } /** * 合并数值 * @param x * @param y * @return 返回最终数值 */ public Formula mergeValue(Formula x, Formula y){ switch (y.operator){ case MUL: return this._mul(x, y); case DIV: return this._div(x, y); case SUB: return this._sub(x, y); default: return this._add(x, y); } } /** * 加法 * @param x * @param y * @return */ public Formula _add(Formula x, Formula y){ int numerator, denominator, numeratorX, numeratorY; denominator = x.denominator * y.denominator; // 分母 numeratorX = (x.integer * denominator + x.numerator * y.denominator) * x.symbol; // x 分子 numeratorY = (y.integer * denominator + y.numerator * x.denominator) * y.symbol; // y 分子 numerator = numeratorX + numeratorY; // 分子和 return new Formula(x.operator, numerator, denominator); } /** * 减法 * @param x * @param y * @return */ public Formula _sub(Formula x, Formula y){ int numerator, denominator, numeratorX, numeratorY; denominator = x.denominator * y.denominator; // 分母 numeratorX = (x.integer * denominator + x.numerator * y.denominator) * x.symbol; // x 分子 numeratorY = (y.integer * denominator + y.numerator * x.denominator) * y.symbol; // y 分子 numerator = numeratorX - numeratorY; // 分子和 return new Formula(x.operator, numerator, denominator); } /** * 除法 * @param x * @param y * @return */ public Formula _div(Formula x, Formula y){ int numerator, denominator, numeratorX, numeratorY; numeratorX = (x.integer * x.denominator + x.numerator) * x.symbol; numeratorY = (y.integer * y.denominator + y.numerator) * y.symbol; numerator = numeratorX * y.denominator; denominator = numeratorY * x.denominator; return new Formula(x.operator, numerator, denominator); } /** * 乘法 * @param x * @param y * @return */ public Formula _mul(Formula x, Formula y){ int numerator, denominator, numeratorX, numeratorY; Operators operator; numeratorX = (x.integer * x.denominator + x.numerator) * x.symbol; numeratorY = (y.integer * y.denominator + y.numerator) * y.symbol; numerator = numeratorX * numeratorY; denominator = x.denominator * y.denominator; return new Formula(x.operator, numerator, denominator); } /** * 判断正数 * @return Boolean */ public Boolean isPositiveNumber(){ return this.symbol == 1; } /** * 向多项式推入一项 * @param x * @return */ public Boolean push(Formula x){ if(this.list == null) this.list = new ArrayList<Formula>(); int integer, denominator, numerator, symbol; integer = this.integer; denominator = this.denominator; numerator = this.numerator; symbol = this.symbol; this.list.add(x); this.injectFormulaValue(); if(symbol != this.symbol){ // 结果为负数,失败 this.list.remove(list.size() - 1); this.integer = integer; this.denominator = denominator; this.numerator = numerator; this.symbol = symbol; return false; } return true; } /** * 输出算式运算结果字符串 * @return */ public String output(){ String str = ""; if(this.symbol == -1) str += "-"; if(this.integer != 0) str += this.integer; if(this.denominator != 0 && this.numerator != 0) { if(this.integer != 0) str += "'" + this.numerator + "/" + this.denominator; else str += this.numerator + "/" + this.denominator; } if(this.integer == 0 && this.numerator == 0) str = "0"; return str; } /** * 读取字符串 * @param formula * @return */ public static Formula calculateFormulaString(String formula){ if(formula == null) return new Formula(); ArrayList<Formula> stack = new ArrayList<Formula>(); stack.add(new Formula()); Formula target = new Formula(), target2; int length = formula.length(), i = -1, position = 1; char c; Boolean isOk = true; Operators operator = Operators.ADD; while (++i < length){ // System.out.println(i + " | " + length); c = formula.charAt(i); if(c == ' ') continue; else if(c == '('){ stack.add(target); target = new Formula(); } else if(c == ')'){ int index = stack.size() - 1; target2 = stack.remove(index); target2.push(target); target = target2; position = 1; } else if(c == '+' || c == '-' || c == '*' || c == '÷') { stack.get(stack.size() - 1).push(target); switch (c){ case '+': operator = Operators.ADD; break; case '-': operator = Operators.SUB; break; case '*': operator = Operators.MUL; break; case '÷': operator = Operators.DIV; break; } target = new Formula(operator); operator = Operators.ADD; position = 1; }else if(c == '\''){ position = 2; }else if(c == '/'){ if(position == 1){ target.numerator = target.integer; target.integer = 0; } position = 3; target.denominator = 0; } else if(c <= '9' && c >= '0'){ int value = Integer.parseInt(c + ""); if(position == 1){ target.integer = target.integer * 10 + value; }else if(position == 2) { target.numerator = target.numerator * 10 + value; }else if(position == 3) { target.denominator = target.denominator * 10 + value; } }else if(c == '=') break; else { System.out.println("- " + "未识别符号("+ (i+1) +"):"+ c); isOk = false; break; } } // System.out.println("> "+formula); if(isOk){ target2 = stack.get(0); target2.push(target); return stack.remove(0); }else { return new Formula(); } } }
Create类
package formula; import java.util.*; public class Create { Random r = new Random(); ArrayList<Formula> list = new ArrayList<Formula>(); Formula e; //生成式子中的第一个操作数(符号只能是+) public Formula CreateFirstOperand(int n){ int a = r.nextInt(n) + 1; //随机产生1-n中的一个操作数 int h = r.nextInt(n) + 1; int g = r.nextInt(h) + 1; int b = r.nextInt(2); if (b==0){ e = new Formula(Formula.Operators.ADD, a); } else { e = new Formula(Formula.Operators.ADD, a, g, h); } return e; } //生成式子中其他的操作数,可以为+,-,*,/ public Formula CreateOtherOperand(int n){ int a = r.nextInt(n) + 1; //随机产生1-n中的一个操作数 int h = r.nextInt(n) + 1; int g = r.nextInt(h) + 1; int b = r.nextInt(2); int c = r.nextInt(4); if(b==0){ switch (c){ case 0:e = new Formula(Formula.Operators.ADD, a);break; case 1:e = new Formula(Formula.Operators.SUB, a);break; case 2:e = new Formula(Formula.Operators.MUL, a);break; case 3:e = new Formula(Formula.Operators.DIV, a);break; } } else{ switch (c){ case 0:e = new Formula(Formula.Operators.ADD, a, g, h);break; case 1:e = new Formula(Formula.Operators.SUB, a, g, h);break; case 2:e = new Formula(Formula.Operators.MUL, a, g, h);break; case 3:e = new Formula(Formula.Operators.DIV, a, g, h);break; } } return e; } //随机生成多项式 public String CreateFormula(int p){ String s = new String(); Create n = new Create(); Formula first,first2,second, third, fourth, i,j,k,l; i = new Formula(); j = new Formula(); l = new Formula(); first = n.CreateFirstOperand(p); first2 = n.CreateFirstOperand(p); second = n.CreateOtherOperand(p); third = n.CreateOtherOperand(p); fourth = n.CreateOtherOperand(p); int OperandNumber = r.nextInt(3); switch (OperandNumber) { //两个操作数 case 0: i.push(first); i.push(second); s = i._print(); break; //三个操作数 case 1: i.push(first); i.push(second); i.push(third); s = i._print(); break; //四个操作数 case 2: int a = r.nextInt(4); switch (a) { case 0: //a+b+c+d i.push(first); i.push(second); i.push(third); i.push(fourth); s = i._print(); break; case 1: int b = r.nextInt(2); switch (b) { case 0: //(a+b+c)+d i.push(first); i.push(second); i.push(third); j.push(i); j.push(fourth); s = j._print(); break; case 1: //a+(b+c+d) int c = r.nextInt(3); switch (c) { case 0: k = new Formula(Formula.Operators.ADD);j = k;break; case 1: k = new Formula(Formula.Operators.SUB);j = k;break; case 2: k = new Formula(Formula.Operators.MUL);j = k;break; } i.push(first); j.push(first2); j.push(second); j.push(third); i.push(j); s = i._print(); break; } break; case 2: int c = r.nextInt(3); int d = r.nextInt(3); switch (d) { case 0: k = new Formula(Formula.Operators.ADD);j = k;break; case 1: k = new Formula(Formula.Operators.SUB);j = k;break; case 2: k = new Formula(Formula.Operators.MUL);j = k;break; } switch (c) { case 0: //(a+b)+c+d i.push(first); i.push(second); j.push(i); j.push(third); j.push(fourth); s = j._print(); break; case 1: //a+(b+c)+d i.push(first); j.push(first2); j.push(second); i.push(j); i.push(third); s = i._print(); break; case 2: //a+b+(c+d) i.push(first); i.push(second); j.push(first2); j.push(third); i.push(j); s = i._print(); break; } break; case 3: //(a+b)+(c+d) int e = r.nextInt(3); switch (e) { case 0: k = new Formula(Formula.Operators.ADD);j = k;break; case 1: k = new Formula(Formula.Operators.SUB);j = k;break; case 2: k = new Formula(Formula.Operators.MUL);j = k;break; } i.push(first); i.push(second); j.push(first2); j.push(third); l.push(i); l.push(j); s = l._print(); break; } break; } return s; } }
Output类
package formula; import java.io.*; import java.util.Scanner; public class Output { public static void main(String[] args)throws IOException{ Create n = new Create(); Formula b; int i, a, r,m; String[] t = new String[20000]; Scanner sc = new Scanner(System.in); PrintStream questionout = new PrintStream("exercise.txt"); PrintStream answerout = new PrintStream("answer.txt"); System.out.println("请输入数值范围:"); a = sc.nextInt(); questionout.print("数字范围:" + a + "\t"); System.out.println("请输入要生成的题目数量:"); i = sc.nextInt(); questionout.println("题目数量:" + i); for(m=1; m<=i; m++){ t[m] = n.CreateFormula(a); questionout.println(m + "、" + t[m] + "="); b = Formula.calculateFormulaString(t[m]); answerout.println(m + "、" + b.output()); } System.out.println("成功生成题目与答案"); } }
五、测试运行

生成一万道题目

六、项目小结
第一次进行结对编程,和舍友分工合作,他负责核心算法(Formula类)的编写,我负责Create类和Output类的编写,有效提高了工作效率。
浙公网安备 33010602011771号