1.项目需求

  a) 除了整数以外,还要支持真分数的四则运算。 (例如:  1/6 + 1/8 = 7/24)

  b) 让程序能接受用户输入答案,并判定对错。 最后给出总共 对/错 的数量。

  c) 逐步扩展功能和可以支持的表达式类型,最后希望能支持下面类型的题目 (最多 10 个运算符,括号的数量不限制)

    25 - 3 * 4 - 2 / 2 + 89 = ?
    1/2 + 1/3 - 1/4 = ? 
    (5 - 4 ) * (3 +28) =?

  d) 一次可以批量出 100 道以上的题目,保存在文本文件中, 并且保证题目不能重复,

2.项目实现

  a)开发环境

    开发工具:MyEclipse、jdk1.8、windows 7

    开发语言:Java

  b)项目设计

    1)主要UML图

    2)主要代码

      a.判断两个数是否互质

        

 1 public static boolean isCoprime(int m,int n){
2 int a=0;
3 int b=0;
4 int c=0;
5 if(m > n) {
6 a = m;
7 b = n;
8 }else{
9 a=n;
10 b=m;
11 }
12 while((c = a % b) != 0) {
13 a = b;
14 b = c;
15 }
16 if(b==1){
17 return true;
18 }
19 return false;
20 }

    b.分数约分

/**
* @param exp 单个分数表达式
* @returned String 返回约分后的分数表达式
* */
public static String afterSimplify(String exp){
String[] num=exp.split("/");
int cop=Integer.parseInt(num[0]);//分子
int deno=Integer.parseInt(num[1]);//分母
if(cop==0){//分子为0
return "0";
}
int max=0;
while(max!=1){
max=maxMultiple(cop, deno);//返回cop、deno的最大公约数
cop/=max;
deno/=max;
}
if(deno==1){
return cop+"";//分数值为1
}else{
return cop+"/"+deno;//化简后的分数
}
}

    c.中缀表达式转化为后缀表达式

/**
* @param infix 中缀表达式
* @returned String 后缀表达式
* */
public static String infix2postfix(String infix){
String postfix="";
int length=infix.length();
Stack st = new Stack();
String c;
for (int i = 0; i < length; i++){
c = infix.substring(i, i+1);
if (c .equals("(")){
st.push(c);
}else if (c.equals(")")){
while (!st.peek().equals("(")){
postfix+= (st.pop()+"#");
}
st.pop();
}else{
try{
Integer.parseInt(c);//判断读到的字符是否为数字
for(int j=0;j<5;j++){//如读到数字,则继续向后读取,直到读到运算符为止
String c_temp="";
if((i+j+2)>length){//判断是否到达输入的字符串的结尾
break;
}
c_temp=infix.substring(i+j+1,i+j+2);
try {
Integer.parseInt(c_temp);//判断独到的字符是否为数字
c+=c_temp;
continue;
} catch (Exception e) {
break;
}
}
i+=(c.length()-1);
postfix+= (c+"#");
}catch(Exception e){
while (!st.empty()&& (comparePri((String)st.peek(), c) >= 0)){
postfix += (st.pop()+"#");
}
st.push(c);
}
}
}
while (!st.empty()){//输入栈中剩余的所有元素
postfix +=(st.pop()+"#");
}
return postfix;
} /**
*@param op1 op2 运算符
*@return int op1、op2的优先级比较结果
* */
public static int comparePri(String op1, String op2){
if (op1 .equals("(")){
return -1;
}else if (op1 .equals("+") || op1 .equals("-")){
if (op2.equals("*") || op2.equals("/")){
return -1;
}
}else if (op1 .equals("*") ||op1 .equals("/")){
if (op2 .equals("+") || op2 .equals("-")){
return 1;
}
}
return 0;
}

    d.表达式求值(整式和分式)

/**
* @param exp 四则运算表达式
* @return 表达式元算结果的最简(分数)形式
* */
public String calculate(String exp){
int a,b,result=0;
String first,second,temp = "";
int first_cop,first_deno,second_cop,second_deno;
Stack s=new Stack();
String[] c=exp.split("#");
//分式求值
if(exp.contains("/")){
for(int i=0;i<c.length;i++){
if(!(c[i].contains("+")||c[i].contains("-")||c[i].contains("*")||c[i].contains("/"))){
s.push(c[i]+"/1");//将整数化为分母为1的分数形式
continue;
}else{
second=(String) s.pop();
first=(String) s.pop();
first_cop=Integer.parseInt(first.split("/")[0]);//第一个分数的分子
first_deno=Integer.parseInt(first.split("/")[1]);//第一个分数的分母
second_cop=Integer.parseInt(second.split("/")[0]);//第二个分数的分子
second_deno=Integer.parseInt(second.split("/")[1]);//第二个分数的分母
if(c[i].equals("+")){//分数相加
temp=(first_cop*second_deno+second_cop*first_deno)+"/"+(first_deno*second_deno);
}else if(c[i].equals("-")){//分数相减
temp=(first_cop*second_deno-second_cop*first_deno)+"/"+(first_deno*second_deno);
}else if(c[i].equals("*")){//分数相乘
temp=(first_cop*second_cop)+"/"+(first_deno*second_deno);
}else if(c[i].equals("/")){//分数相除
temp=(first_cop*second_deno)+"/"+(first_deno*second_cop);
}
s.push(temp);//将计算结果压入栈中
}
}
//将最终结果约分后返回
return Simplify.afterSimplify((String) s.pop());
}else{
//整式求值
for(int i=0;i<c.length;i++){
try{
Integer.parseInt(c[i]);//判断是否为数字
s.push(c[i]);
continue;
}catch(Exception e){
b=Integer.parseInt((String) s.pop());
a=Integer.parseInt((String) s.pop());
if(c[i].equals("+")){
result=a+b;
}else if(c[i].equals("-")){
result=a-b;
}else if(c[i].equals("*")){
result=a*b;
}
s.push(result+"");
}
}
}
//返回整数运算结果
return result+"";
}

    e.随机生成纯整式、纯分式、混合表达式

if(type.equals("1")){//整式运算
for (int i = 0; i < count; i++) {//生成count个正式
questions.add(b.zhengshi(min, max));
}
}else if(type.equals("2")){//分式运算
for (int i = 0; i < count; i++) {//生成count个分式
questions.add(b.fenshi(deno));
}
}else if(type.equals("3")){//混合运算
for (int i = 0; i < count; i++) {//生成count个混合元算表达式
int length=r.nextInt(4)+3;//新加的符号个最最多为6个
String op,exp="";
for(int j=0;j<length;j++){
op=ops[r.nextInt(2)];//随机选取运算符号 '+'或'*'
if(op.equals("+")){
if(r.nextInt(2)==1){
exp=exp+b.zhengshu(min, max)+"+";
}else{
exp=exp+b.fenshu(deno)+"+";
}
}else if(op.equals("*")){
if(exp.length()==0){
exp=r.nextInt(9)+2+"+";
}
if(r.nextInt(2)==1){//随机选取整式或整数
String item=b.zhengshi(min, max);
while(item.contains("*")||item.contains("/")){
item=b.zhengshi(min, max);
}
item="("+item+")";
if((exp.substring(0,exp.length()-1).contains("+")||exp.substring(0,exp.length()-1).contains("-"))
&&!exp.substring(0,exp.length()-1).contains("*")
&&!exp.substring(0,exp.length()-1).contains("/")){
exp="("+exp.substring(0,exp.length()-1)+")*"+item+"+";
}else{
exp=exp.substring(0,exp.length()-1)+"*"+item+"+";
}
}else{
String item=b.zhengshu(min, max);
if((exp.substring(0,exp.length()-1).contains("+")||exp.substring(0,exp.length()-1).contains("-"))
&&!exp.substring(0,exp.length()-1).contains("*")
&&!exp.substring(0,exp.length()-1).contains("/")){
exp="("+exp.substring(0,exp.length()-1)+")*"+item+"+";
}else{
exp=exp.substring(0,exp.length()-1)+"*"+item+"+";
}
}
}
}
if(!exp.equals("")&&(exp.subSequence(exp.length()-1, exp.length()).equals("+"))){
exp=exp.substring(0,exp.length()-1);//剔除表达式末尾的加号
}

  f.题目重复性检测

public class CheckRepeat {

    /**
*@author GuoQingYun
*@param list 以生成的题目组成的集合,集合呢各题均不重复
*@param exp 新生成的待检测的表达式
*@param BaseGenerator的对象
*@return true-新生成的表达式与之前的重复 false-新生成的表达式与之前的不重复
* */
public static boolean check(List list,String exp,BaseGenerator b){
String latterVal=b.calculate(Convert.infix2postfix(exp));
List formorOperator=new ArrayList();
List latterOperator=new ArrayList();
List formorNumber=new ArrayList();
List latterNumber=new ArrayList();
for(int i=0;i<list.size();i++){
//判断两个表达式的计算结果是否相等
if(b.calculate(Convert.infix2postfix(list.get(i).toString())).equals(latterVal)){
formorOperator=extractOperator(list.get(i).toString());
latterOperator=extractOperator(exp);
//判断两个表达式的运算符合是否完全一一匹配
if(compare(formorOperator, latterOperator)){
formorNumber=extractNumber(list.get(i).toString());
latterNumber=extractNumber(exp);
//判断两个表达式中包含的整数项是否完全一一匹配
if(compare(formorNumber, latterNumber)){
return true;
}
}
}
}
return false;
} /**
* @author GuoQingYun
* @param exp -四则运算表达式
* @return List -从表达式exp中分解出来的所有运算符的集合
* */
public static List extractOperator(String exp){
List operator=new ArrayList();
String c="";
exp=exp.replace("(", "");//剔除掉表达中包含的括号
exp=exp.replace(")", "");
for (int i = 0; i < exp.length(); i++) {
c=exp.substring(i,i+1);//逐个扫描表达式中的字符
if(c.equals("+")||c.equals("-")||c.equals("*")||c.equals("/")){
operator.add(c);
}
}
return operator;
} /**
* @author GuoQingYun
* @param exp -四则运算表达式
* @return List -从表达式exp中分解出来的所有整数的集合
* */
public static List extractNumber(String exp){
List number=new ArrayList();
String c="";
exp=exp.replace("(", "");//剔除掉表达式中包含的括号
exp=exp.replace(")", "");
for (int i = 0; i < exp.length(); i++) {
c=exp.substring(i,i+1);
for(int j=0;j<5;j++){//如读到数字,则继续向后读取,直到读到运算符为止
String c_temp="";
if((i+j+2)>exp.length()){//判断是否到达输入的字符串的结尾
break;
}
c_temp=exp.substring(i+j+1,i+j+2);
try {
Integer.parseInt(c_temp);//判断独到的字符是否为数字
c+=c_temp;
continue;
} catch (Exception e) {
break;
}
}
i+=(c.length()-1);
number.add("c");
}
return number;
} /**
* @author GuoQingYun
* @param formor -以存在的与其他表达式不重复的表达式中包含的运算符或整数的集合
* @param latter -新生成的表达式中包含的运算符或整数的集合
* @return boolean -true:formor与latter元素种类个元素个数完全匹配
* -false:formor与latter元素种类个元素个数不完全匹配
* */
public static boolean compare(List formor,List latter){
if(formor.size()!=latter.size()){
//两个表达式运算符或整数项不是一一匹配
return false;
}else{
for(int i=0;i<formor.size();i++){
if(formor.contains(latter.get(i))){
formor.remove(latter.get(i));//剔除掉已经比较过的项
latter.remove(i);
continue;
}else{
//两个表达式的运算符或整数项不是一一匹配
return false;
}
}
//两个表达式的运算符或整数项一一匹配
return true;
}
}
}

  c)测试结果

    1)整式运算

  2)分式运算

  3)混合运算

3.总结

  目前各项需求已基本达成,实验结果也比较令人满意。但也有不足之处,比如:题目生成规则优待有待改善等。这些问题将会在下一阶段逐步解决。

    

第一章-第一题(小学生四则运算)--By郭青云的更多相关文章

  1. Java程序设计(2021春)——第一章课后题(选择题+编程题)答案与详解

    Java程序设计(2021春)--第一章课后题(选择题+编程题)答案与详解 目录 Java程序设计(2021春)--第一章课后题(选择题+编程题)答案与详解 第一章选择题 1.1 Java与面向对象程 ...

  2. ASP.NET自定义控件组件开发 第一章 第一章:从一个简单的控件谈起

    第一章:从一个简单的控件谈起 系列文章链接: ASP.NET自定义控件组件开发 第一章 待续 ASP.NET自定义控件组件开发 第一章 第二篇 接着待续 ASP.NET自定义控件组件开发 第一章 第三 ...

  3. 第一章-第二题Unity3D游戏引擎相关--By林培文

    1) 此类软件是什么时候开始出现的, 这些软件是怎么说服你(陌生人)成为他们的用户的?  他们的目标都是盈利么?  他们的目标都是赚取用户的现金么?还是别的? 2004年,Unity3D诞生于丹麦哥本 ...

  4. 《python语言程序设计》_第一章编程题

    题目1.1 :显示"welcome to python " 答案:print('welcome to python') 题目1.2:显示"welcome to pytho ...

  5. jQuery框架分析第一章: 第一个匿名函数

    我的jQuery版本为1.7* 这个版本代码比之前的版本优化了很多,结构也清晰了不少,就用最新的吧. 打开jQuery源代码 首先你能看到所有代码被一个 (function(window,undefi ...

  6. c语言第一章第一节 认识变量

    声明:本人大一新生,闲着无聊..写写c语言教程..菜鸟一枚..大神勿喷!!! 接下来我们都用dev来进行编译..vc++太古老了,没提示功能,不好上手,并且老是出毛病..vs太大了,编个c不至于,运行 ...

  7. Zabbix简介(第一章第一节)

    Alexei Vladishev创建了Zabbix项目,当前处于活跃开发状态,Zabbix SIA提供支持. Zabbix是一个企业级的.开源的.分布式的监控套件 Zabbix可以监控网络和服务的监控 ...

  8. 【第一章第一回】BootStrap 简介

    Twitter Bootstrap 是目前最受欢迎的前端框架,它简洁.直观.移动优先.强悍的前端开发框架,让web开发更迅速.简单.基于HTML.CSS和Javascript. 为什么使用Bootst ...

  9. tensorflow2.0学习笔记第一章第一节

    一.简单的神经网络实现过程 1.1张量的生成 # 创建一个张量 #tf.constant(张量内容,dtpye=数据类型(可选)) import tensorflow as tf import num ...

随机推荐

  1. C和指针 第十二章 结构体 整体赋值 error: expected expression

    定义结构体后整体赋值时发生错误 typedef struct NODE { struct NODE *fwd; struct NODE *bwd; int value; } Node; //声明变量 ...

  2. C和指针 第五章 位数组

    5.4的习题:编写一组函数,实现维数组,函数原型如下: //指定位设置为1void set_bit(char bit_array[], unsigned bit_number); //指定位清零 vo ...

  3. HTML文档、javascript脚本的加载与解析

    1.onload事件 1.1 onload事件分类 a.文档加载完成事件(包括脚本.图片等资源都加载完),绑定方法:<body onload="doSomething()"& ...

  4. Linq查询表达式

    目录 1. 概述 2. from子句 3. where子句 4. select子句 5. group子句 6. into子句 7. 排序子句 8. let子句 9. join子句 10. 小结 1. ...

  5. UIPickerView选择器的使用方法

    UIPickerView是选择列表内容的控件 使用方法与UITableView类似 都需要用array传入数据 用Delegate DataSource中的代理方法实现各种显示功能 @interfac ...

  6. poj1001_Exponentiation_java高精度

    Exponentiation Time Limit: 500MS   Memory Limit: 10000K Total Submissions: 162918   Accepted: 39554 ...

  7. VisualStudio控制台输出窗口一闪而过

    我用到开发环境是visual studio 2010,写的简单的控制台程序,结果一按control+F5输出窗口出现后立刻就消失了(平时很少这样的呀),按照以往经验,加上了在程序结尾getchar() ...

  8. jquery 键盘回车事件

    <input id="search" placeholder="输入要领用的资产条码" id="scanCode" type=&quo ...

  9. istringstream、ostringstream、stringstream 类简介

    本文系转载,原文链接:http://www.cnblogs.com/gamesky/archive/2013/01/09/2852356.html ,如有侵权,请联系我:534624117@qq.co ...

  10. NSLOOKUP命令使用

    nslooup命令,可以用来检测dns服务器是否可用,以及域名对应的真实ip,在一些网络dns不稳定的情况下可以使用,用来正确访问网站. Microsoft Windows [版本 6.1.7601] ...