四则运算程序
Posted 吴一楠
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了四则运算程序相关的知识,希望对你有一定的参考价值。
⦁作业题目:http://www.cnblogs.com/HQL0301/p/7502315.html
1.需求分析:
⦁根据用户所给参数设置出题难度,操作数范围,题目和答案输出路径
⦁根据用户提供的题目和答案文件来对用户答案进行判断对错
⦁实现+,-,x,÷四则运算
⦁实现分数的计算,包括真分数
⦁生成的表达式包含括号且在计算时要精准识别计算
⦁实现表达式的查重,例如1+2+3和3+2+1是重复的
2.功能设计
⦁在开始程序前先验证命令行传入参数是否正确
⦁根据难度系数和操作数范围随机生成整数和分数
⦁随机生成运算符并将其与随机数组成算式
⦁计算题目结果
⦁将题目和答案输出到指定文件
⦁读入现有题目和用户答案文件对其作答进行判断对错
⦁将作答情况输出到指定文件
⦁设置题目难度系数:1--含+-运算,操作数不含分数;
2--含+-x运算,操作数含分数;
3--含+-x÷运算,操作数含分数;
3.设计实现
采用Java实现,共有四个类:
⦁Question类:主类,识别用户输入参数,根据参数调用不同函数
⦁Arithmetic类:根据难度系数和操作数范围生成整数或分数,还有运算符,随机对局部添加括号最后将其拼接成算式将其返回
⦁Calculate类:对题目进行计算,返回题目答案
⦁Save类:将题目,答案,成绩信息存储到文件中
4.代码说明
//合成算式
public String CreateArith(int degree,int range){
String s = new String();
//存储加完括号的算式String ss = new String();
s = s + Createnum(degree,range);
//生成算式运算符个数的随机数
Random random = new Random();
int pis= random.nextInt(3)+1;
//至多三个操作数,两个运算符
for(int i = 0;i < pis;i++){
//利用随机数控制新生成的运算符和数字添加在原来公式的前方还是后方
//以实现括号可以出现在前半部和后半部
String sym = CreateSymbol(degree);
String num = Createnum(degree,range);
int dir = (int)( Math.random() * 10)+1;
if(dir>5){
s = s + sym + num ;
}
else{
s = num + sym + s;
}
//对算式添加括号
if(i<2){
int r = (int)( Math.random() * 10);
if(r<5) {
AddBracket(s);
}
}
}
return s;
}
//将表达式中含括号的表达式找出并局部计算之
public String FindBrack(String equation){
String temp = new String();
String result = new String();
String ans = new String();
//查找左括号在表达式中的位置
int left = equation.lastIndexOf(\'(\');
//若表达式没有括号则直接计算
if(left==-1){
ans = cal(equation);
return ans;
} else{
//查找与之匹配的右括号
int right = equation.indexOf(\')\', left);
if(right==-1){
throw new RuntimeException("the equation is wrong!");
}else{
//匹配成功则截取出括号内算式进行计算
temp = equation.substring(left+1, right);
result = cal(temp);
//将计算完的结果直接拼接回原算式!方便得到最终结果
equation = equation.substring(0,left)+result+equation.substring(right+1);
return FindBrack(equation);
}
}
}
//获取操作数
private List<String> GetNum(String equation) {
equation = FindMinus(equation);
Pattern pt = Pattern.compile("\\\\+|\\\\-|\\\\*|\\\\÷");
String[] split = pt.split(equation);
//对提取出的数字进行判断是否含F,是的话将其转成负数
List<String> list = new ArrayList<>();
for(int i=0;i<split.length;i++){
String number = split[i];
if(number.equals("F")){
number = "-"+number.substring(1);
}
if(number.contains("/")) {
list.add(number);
}else {
number = number+"/"+String.valueOf(1);
list.add(number);
}
}
return list;
}
//计算 拿除法举例
public String cal(String equation){
//每次调用获取最新的算式中的操作符
List<String> operator = GetSym(equation);//获取操作符
List<String> number = GetNum(equation); //获取操作数
String str = new String();
String ans = new String();
String num1 = new String();
String num2 = new String();
int[] a = {};
int[] b = {};
//先乘除后加减:先操作乘除号,操作完移除,最后遍历加减号即可完成操作
for(int i=0;i<=operator.size()-1;i++){
str = operator.get(i);//运算并用运算结果替换操作数的位置
if(str.equals("*")){
num1 = number.remove(i);
num2 = number.remove(i);
int temp = 0;
temp = num1.indexOf(\'/\');
a[0]= Integer.parseInt(num1.substring(0,temp));
a[1]= Integer.parseInt(num1.substring(temp+1));
temp = num2.indexOf(\'/\');
b[0]= Integer.parseInt(num2.substring(0,temp));
b[1]= Integer.parseInt(num2.substring(temp+1));
a[0] = a[0]*b[0]; //分子相乘
a[1] = a[1]*b[1]; //分母相乘
int d=common_divisor(a[0],a[1]);
a[0] = a[0]/d;
a[1] = a[1]/d;
num1 = String.valueOf(a[0])+"/"+String.valueOf(a[1]);
operator.remove(i);
number.add(i, num1);
i--; //防止漏掉运算符
}
//返回计算结果
if(operator.size()==0) {
num1 = number.get(0);
int temp = 0;
temp = num1.indexOf(\'/\');
a[0]= Integer.parseInt(num1.substring(0,temp));
a[1]= Integer.parseInt(num1.substring(temp+1));
//真分数结果
if(a[0]>a[1]) {
temp = a[0] / a[1];
a[0] = a[0] % a[1];
if(a[0]!=0)
num1 = String.valueOf(temp)+"\'"+String.valueOf(a[0])+"/"+String.valueOf(a[1]);
else
num1 = String.valueOf(temp);
}
if(a[0]==a[1]) num1 = String.valueOf(1);
}
return num1;
}
//读入题目和答案并判断对错
public boolean judge(String que,String ans,String gra){
List<String> answer = new ArrayList<String>();
List<String> question = new ArrayList<String>();
List<String> grade = new ArrayList<String>();
File ansFile=new File("D:\\\\"+ans); //答案文件
File queFile=new File("D:\\\\"+que);//题目文件
if(!queFile.isDirectory()||!ansFile.isDirectory()){
System.out.println("文件不存在!");
}else{
System.out.println("正在加载中...");
}
BufferedReader reader=null;
String s=null;
int line=1;
try{
reader=new BufferedReader(new FileReader(ansFile));
while((s=reader.readLine())!=null){
answer.add(s);
line++;
}
BufferedReader bufferedReader = reader=new BufferedReader(new FileReader(queFile));
System.out.println("读入的题目为:");
while((s=reader.readLine())!=null){
question.add(s);
System.out.println(s);
line++;
}
}
catch(Exception e){
e.printStackTrace();
}
finally{
if(reader!=null){
try{
reader.close();
}
catch(Exception e){
e.printStackTrace();
}
}
}
//判断是否正确
Calculate cal = new Calculate();
String rightNum = "(";
String wrongNum = "(";
int rightCnt = 0;
int wrongCnt = 0;
int ansCnt = answer.size();
int queCnt = question.size();
if(ansCnt!=queCnt){
System.out.println("题目数量与答案数量不符,请检查。");
return false;
}
for(int i = 0;i<ansCnt;i++){
String str1 =null;
String str2 =null;
str1 = answer.get(i);
str2 = question.get(i);
if(Integer.parseInt(cal.FindBrack(str2))!=Integer.parseInt(str1)){
System.out.println("回答:"+ cal.FindBrack(str1));
System.out.println("答案:"+ cal.FindBrack(str2));
wrongCnt++;
str1="0";
grade.add(str1);
wrongNum = wrongNum + String.valueOf(i+1) + ",";
}
else{
str1="1";
grade.add(str1);
rightCnt++;
rightNum = rightNum + String.valueOf(i+1) + ",";
}
}
rightNum = rightNum.substring(0, rightNum.length()-2)+")";
wrongNum = wrongNum.substring(0, wrongNum.length()-2)+")";
//输出结果
List<String> report = new ArrayList<String>();
report.add("Correct: "+String.valueOf(rightCnt)+" "+rightNum);
report.add("Wrong: "+String.valueOf(wrongCnt)+" "+wrongNum);
byte[] buff=new byte[]{};
int num = report.size();
try
{
for(int i = 0;i < num;i++){
String aa= (String)report.get(i);
String path = "D://"+gra;
buff=aa.getBytes();
if(i==0){
FileOutputStream out=new FileOutputStream(path,false);
out.write(buff,0,buff.length);
out.write("\\r\\n".getBytes());
}
else{
FileOutputStream out=new FileOutputStream(path,true);
out.write(buff,0,buff.length);
out.write("\\r\\n".getBytes());
}
}
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
return true;
}
5.测试运行:
6.PSP:
PSP2.1 | Personal Software Process Stages | Time Senior Student | Time |
Planning | 计划 | 10 | 10 |
· Estimate | 估计这个任务需要多少时间 | 10 | 10 |
Development | 开发 | 170 | 190 |
· Analysis | 需求分析 (包括学习新技术) | 15 | 15 |
· Design Spec | 生成设计文档 | 10 | 10 |
· Design Review | 设计复审 | 10 | 5 |
· Coding Standard | 代码规范 | 20 | 15 |
· Design | 具体设计 | 20 | 15 |
· Coding | 具体编码 | 60 | 80 |
· Code Review | 代码复审 | 20 | 35 |
· Test | 测试(自我测试,修改代码,提交修改) | 15 | 15 |
Reporting | 报告 | 30 | 26 |
· | 测试报告 | 5 | 5 |
· | 计算工作量 | 5 | 4 |
· | 并提出过程改进计划 | 2 | 2 |
第一次采用PSP的方式统计开发时间,发现是一个非常好的流程,各项工作流程都计划的很清晰,这次由于经常忘记计划时间所以与实际时间出入较大,在代码复审时发现分数的计算问题在执行中并没有解决,于是多花费了一些时间。
Coding.net地址: https://git.coding.net/wknyhu/Calculator.git
7.小结:
这次实验总体来说思路比较清晰,由于老师多次提示过并且与同学交换过意见。通过这次开发过程又学习到了很多,比如处理分数的思路,存储和读入文件的方式以及中缀表达式转后缀,二叉树查重,对燃查重没实现,但是具体思路已经学习了。自我评价在代码规范方面还欠缺,因为Java开发经验较少,对于详细的代码规范还有些许不了解,本次开发并没有将其实现为一个具体可用的程序,希望后续的开发过程中可以逐步精通Java知识并且将本程序具体实现。
以上是关于四则运算程序的主要内容,如果未能解决你的问题,请参考以下文章
获取 badarith,[erlang,'+',[error,0],[],同时使用 Erlang 片段在 TSUNG 中执行算术运算