现代软件工程_第一周练习_第1题_万世想

第一题是要求实现一个自动生成小学生加减乘除四则运算题目的程序。后面可以将它扩展为网站或安卓应用或IOS应用或win10应用。

我的思路比较简单。环境是Java JDK1.8;IDE为Intellij社区版。

首先,我们不考虑有括号的情形,那么符号只有+、-、*、/四种;涉及到的数包含两种:整数或分数。

1. 我们注意到,一个运算式中,总有“数的个数比运算符多1”的规则。于是,我们自然地想到创建一个固定长度为n的数组number存放数字,每个数都能随机生成,通过maxOfNumber变量控制式子中出现的最大数字。创建一个长度为n-1的数组character存放运算符号。

2. 接下来需要初始化数组number和character。number数组每个元素靠maxOfNumber控制最大数、minOfNumber控制最小数、hasFraction控制是否出现分数随机生成;character数组每个元素靠type变量控制只有加减、只有乘除、加减乘除都有的3种类型随机生成。

例如:n为5,minOfNumber为0,maxOfNumber为10,hasFraction为出现分数,type为只有加减的类型:5/7+8/7-1/7-2/7

3. 接下来就是结果的计算。对于纯整数,计算结果是简单的。通过查找资料,我发现纯整数字符串的计算依靠ScriptEngine类即可完成。函数使用示例如下:

 1     //整型表达式的正确计算结果
 2     public String calIntResult() {
 3         ScriptEngine se = new ScriptEngineManager().getEngineByName("JavaScript");
 4         try {
 5             Double result = (Double) se.eval(formular);
 6             return String.valueOf(result.doubleValue());
 7         } catch (ScriptException e) {
 8             e.printStackTrace();
 9         }
10         return null;
11     }

然而,对于分数,这种方法是不行的。比如1/5+2/3这样的式子,靠字符串渲染肯定行不通。依靠原始的数学求解方法,意识到需要借助求最大公约数和最小公倍数完成。例:求12和8的最小公倍数。12和8的最大公约数为4,12×8÷4=24 ,所以两数的最小公倍数是24。下面放上分数加减乘除法的简单实现。

 1 public class Fraction {
 2     static int numera = 0;
 3     static int deomina = 0;
 4
 5     public static void main(String[] args) {
 6         int a1 = 9;
 7         int a2 = 10;
 8         int b1 = 3;
 9         int b2 = 11;
10         new Fraction().fracAdd(a1,a2,b1,b2);//结果为:11/20
11         System.out.println("分数加法运算:"+numera+"/"+deomina);
12         new Fraction().fracSub(a1,a2,b1,b2);//分数相减
13         System.out.println("分数减法运算:"+numera+"/"+deomina);
14         new Fraction().fracMul(a1,a2,b1,b2);//分数相乘
15         System.out.println("分数乘法运算:"+numera+"/"+deomina);
16         new Fraction().fractDiv(a1,a2,b1,b2);//分数相除
17         System.out.println("分数除法运算:"+numera+"/"+deomina);
18     }
19
20     //定义分数相加函数
21     public void fracAdd(int first_numerator, int first_denominator, int second_numrator, int second_denominator){
22         int lcm, gcd;
23         lcm = lcm(first_denominator,second_denominator);//需要调用求最小公倍数的函数求的最小公倍数
24         numera = (lcm/first_denominator)*first_numerator+(lcm/second_denominator)* second_numrator;//  未化简的分子和
25         deomina = lcm;             //未化简的分母
26         gcd = gcd(numera,deomina); //需要调用求最大公约数的函数
27         numera = numera/gcd;       //化简后的分子
28         deomina = deomina/gcd;     //化简后的分母
29     }
30
31     //定义分数相减函数
32     public void fracSub(int first_numerator,int first_denominator,int second_numrator,int second_denominator){
33         int lcm, gcd;
34         lcm = lcm(first_denominator,second_denominator);//需要调用求最小公倍数的函数求的最小公倍数
35         numera = (lcm/first_denominator)*first_numerator-(lcm/second_denominator)* second_numrator;//  未化简的分子差
36         deomina = lcm;             //未化简的分母
37         gcd = gcd(numera,deomina); //需要调用求最大公约数的函数
38         numera = numera/gcd;       //化简后的分子
39         deomina = deomina/gcd;     //化简后的分母
40     }
41
42     //定义分数相乘函数
43     public void fracMul(int first_numerator,int first_denominator,int second_numrator,int second_denominator){
44         int z, m, gcd;
45         z = first_numerator * second_numrator;
46         m = first_denominator * second_denominator;
47         gcd = gcd(z,m);
48         numera = z / gcd;
49         deomina = m / gcd;
50     }
51
52     //定义分数相除函数
53     public void fractDiv(int first_numerator,int first_denominator,int second_numrator,int second_denominator){
54         int z, a, m, gcd;
55         a = second_denominator;
56         second_denominator = second_numrator;
57         second_numrator = a;
58         z = first_numerator * second_numrator;
59         m = first_denominator * second_denominator;
60         gcd = gcd(z,m);
61         numera = z / gcd;
62         deomina = m / gcd;
63     }
64
65     //求最大公约数
66     public static int gcd(int m,int n){
67         int i = 2;       //定义整型变量i,为循环变量
68         int g, min;
69         min = m>n ? n : m;
70         g = 1;           //最大公约数初始值为1
71         while(i <= min)  //判断条件,一直循环到两个数中较小的那个结束
72         {
73             while (m % i == 0 && n % i == 0)
74             {
75                 m = m / i;
76                 n = n /i;
77                 g = g * i;
78             }
79             i++;
80         }
81         return g;
82     }
83
84     //求最小公倍数函数
85     public static int lcm(int m,int n){
86         int g, l;
87         g = gcd(m,n);       //调用求最大公约数函数
88         l = m * n / g;
89         return l;
90     }
91 }   

4. 整数和分数的自动生成已经OK,计算结果方法也实现了。下面放上另一个类的具体代码。该代码与上面的代码一起实现了题目一的要求。

  1 public class AutoFormula {
  2     static String formular = new String();
  3     static String result = new String();
  4     int numerator;
  5     int denominator;
  6
  7     public static void main(String[] args) {
  8         /*
  9          * 参数mode为符号模式,0是加减、1是乘除、2是加减乘除;
 10          * 参数hasFraction为控制分数个数;
 11          * 参数numOfCharacter为符号数量;
 12          * 参数minOfNumber为式子中出现的最小数值;
 13          * 参数maxOfNumber为式子中出现的最大数值;
 14          */
 15         new AutoFormula().generate(0, 1, 3, 0, 10);
 16         System.out.println(formular);
 17         System.out.println(result);
 18     }
 19
 20
 21     public void generate(int mode, int hasFraction, int numOfCharacter, int minOfNumber, int maxOfNumber) {
 22         int numOfNumber = numOfCharacter + 1;
 23         String[] character = new String[numOfCharacter];
 24         String[] number = new String[numOfNumber];
 25         StringBuilder stringBuilder = new StringBuilder();
 26
 27         //初始化符号数组
 28         for (int i=0; i<character.length; i++) {
 29             character[i] = generateCharacter(mode);
 30         }
 31         //初始化数字数组
 32         for (int i=0; i<number.length; i++) {
 33             number[i] = generateNumber(hasFraction, minOfNumber, maxOfNumber);
 34         }
 35         //链接符号和数字
 36         stringBuilder.append(number[0]);
 37         for (int i=0; i<character.length; i++) {
 38             stringBuilder.append(character[i] + number[i+1]);
 39         }
 40         formular = stringBuilder.toString();
 41
 42         if (hasFraction == 0) {
 43             result = calIntResult();
 44         } else {
 45             result = calFractionResult(number, character);
 46         }
 47     }
 48
 49
 50     //3种随机生成模式,随机生成加减、乘除、加减乘除符号
 51     public String generateCharacter(int mode) {
 52         Random random = new java.util.Random();
 53         int i;
 54         switch (mode) {
 55         case 0:
 56             //+ -
 57             i = random.nextInt(2);
 58             return (i==0) ? "+" : "-";
 59         case 1:
 60             //* /
 61             i = random.nextInt(2);
 62             return (i==0) ? "*" : "/";
 63         case 2:
 64             //+ - * /
 65             i = random.nextInt(4);
 66             return (i==0) ? "+" : (i==1) ? "-" : (i==2) ? "*" : "/";
 67         }
 68         return null;
 69     }
 70
 71
 72     //2种随机生成模式,随机生成整数、分数
 73     public String generateNumber(int mode, int min, int max) {
 74         Random random = new java.util.Random();
 75         switch (mode) {
 76         case 0:
 77             //随机生成整数
 78             int num = min + random.nextInt(max);
 79             while (num == 0) { //整数为0太简单
 80                 num = min + random.nextInt(max);
 81             }
 82             return String.valueOf(num);
 83         case 1:
 84             //随机生成分数
 85             int numerator;
 86             int denominator;
 87             do { //分子为0太简单,分母不能为0或1,分子分母不能相等
 88                 numerator = min + random.nextInt(max);
 89                 denominator = min + random.nextInt(max);
 90             } while (numerator == 0 || denominator == 0 || denominator == 1 || denominator == numerator);
 91             return String.valueOf(numerator) + "/" + String.valueOf(denominator);
 92         }
 93         return null;
 94     }
 95
 96
 97     //整型表达式的正确计算结果
 98     public String calIntResult() {
 99         ScriptEngine se = new ScriptEngineManager().getEngineByName("JavaScript");
100         try {
101             Double result = (Double) se.eval(formular);
102             return String.valueOf(result.doubleValue());
103         } catch (ScriptException e) {
104             e.printStackTrace();
105         }
106         return null;
107     }
108
109
110     //分数型表达式的正确计算结果
111     public String calFractionResult(String[] number, String[] character) {
112         int first_numerator;
113         int first_denominator;
114         int second_numrator;
115         int second_denominator;
116         splitFraction(number[0]);
117         first_numerator = numerator;
118         first_denominator = denominator;
119         for (int i=0; i<character.length; i++) {
120             splitFraction(number[i+1]);
121             second_numrator = numerator;
122             second_denominator = denominator;
123             Fraction fraction = new Fraction();
124             switch (character[i]) {
125             case "+":
126                 fraction.fracAdd(first_numerator, first_denominator, second_numrator, second_denominator);
127                 first_numerator = Fraction.numera;
128                 first_denominator = Fraction.deomina;
129                 break;
130             case "-":
131                 new Fraction().fracSub(first_numerator, first_denominator, second_numrator, second_denominator);
132                 first_numerator = Fraction.numera;
133                 first_denominator = Fraction.deomina;
134                 break;
135             case "*":
136                 new Fraction().fracMul(first_numerator, first_denominator, second_numrator, second_denominator);
137                 first_numerator = Fraction.numera;
138                 first_denominator = Fraction.deomina;
139                 break;
140             case "/":
141                 new Fraction().fractDiv(first_numerator, first_denominator, second_numrator, second_denominator);
142                 first_numerator = Fraction.numera;
143                 first_denominator = Fraction.deomina;
144                 break;
145             }
146         }
147
148         if (first_numerator == 0) {
149             return "0";
150         } else if (first_numerator == first_denominator) {
151             return "1";
152         } else {
153             return first_numerator + "/" + first_denominator;
154         }
155     }
156
157
158     //将分数拆分开
159     public void splitFraction(String fraction) {
160         if (fraction.contains("/")) {
161             String[] tmpNumber = fraction.split("/");
162             numerator = Integer.parseInt(tmpNumber[0]);
163             denominator = Integer.parseInt(tmpNumber[1]);
164         } else { //整数就直接分子分母相同
165             numerator = Integer.parseInt(fraction);
166             denominator = numerator;
167         }
168     }
169
170 }

5. 做到这里,您可能会问:

为什么你要用Java语言实现呢?使用Python语言实现会不会更简单呢?

答:嗯,Python实现的确更简单,但是我们最后要做的当然是将它实现成一个网站或App。如果实现成网站,基于Spring MVC+Spring+Hibernate/Mybatis的Java Web拥有着更强大的逻辑表达能力以及更耦合、更稳定的技术架构。Java的强面向对象语言特性也能够更好地帮助团队严格化代码的编写,利于软件工程团队协作开发,Python弱语法的特点不利于规范代码,在后期维护更强大的功能时势必会复杂。PHP则只能应用于网站建设,后期不利于转型为Android应用,因此它不在我们的考虑范围内。.NET则只能用于微软服务器,这对于挚爱Linux的我。。。无法忍受。

为什么你要用Intellij IDE呢?Eclipse或者MyEclipse你咋不用?

答:这个问题已经讨论透了。我喜欢Intellij的原因是它非常完善的代码提示功能,即使你在写CSS或Javascript脚本时,它都有HTML5特性的语法提示,更别提Java各种类、包、函数的精巧提示了;此外,它无条件支持Maven,Gradle这些Java的项目管理工具,必须点个大写的赞。

6. 既然我们打算将这个服务做成网站,并且是基于Java SSH框架的,那么前端我暂时使用Bootstrap框架,上手简单,对于这个项目,足够了。

我们团队的Github代码托管地址为:https://github.com/NorthWolives/。里面包含基础的运算式生成代码以及目前网站前端实现的代码。

这是我的前端页面简单实现:http://server.malab.cn/PupilLearn/

首页截图如下,希望未来小朋友们喜欢:

时间:2016年9月9日

作者:万世想,天津大学计算机学院计算机科学与技术系

时间: 2024-12-23 14:15:13

现代软件工程_第一周练习_第1题_万世想的相关文章

现代软件工程_第一周练习_第5题_万世想

这道题的题目是: 你所在的学校有计算机科学专业和软件工程专业么?相关专业的教学计划和毕业出路有什么不同?阅读有关软件工程和计算机科学的区别的文章,谈谈你的看法. 我来自天津大学计算机科学技术学院,计算机科学技术专业.选修的这门课是现代软件工程,由于之前本科我跟随导师做过一些软件工程的学术研究,因此很喜欢这门课.同时也倾慕邹欣老师许久.嗯,微博粉丝,哈哈哈.因此,学校是有计算机科学技术专业以及软件工程专业. 那么,这两个的区别是什么呢?我的理解概括为:计科重理论,软工重技能.从排课情况来看,计科大

网易云课堂_C语言程序设计进阶_第一周:数据类型:整数类型、浮点类型、枚举类型

C语言程序设计进阶_第一周:数据类型:整数类型.浮点类型.枚举类型 1.0数据类型 1.1整数类型 1.2浮点类型 1.3逻辑类型 1.4类型转换和条件运算 1.0数据类型 1 整数 char(%c), short, int(%d), long(%ld), long long(C99) 2 浮点数 float(%f), double(%lf), long double(C99) 3 逻辑 bool(C99) 4 指针 5 自定义类型 所表达的数的范围:char<short<int<flo

现代软件工程_第一周练习_第11题

我们不是在真空里谈软件工程, 软件要运行在硬件芯片上面, 下面看看一个计算机芯片的发展历史: http://perspectives.mvdirona.com/2014/09/august-21-2014-computer-history-museum-presentation/ http://mvdirona.com/jrh/TalksAndPapers/DileepBhandarkarAmazingJourneyFromMainframesToSmartphones.pdf https://

现代软件工程_第一周练习_第9题_团队采访

我们对上一届一个学长进行了采访,由于不在本地,就进行了电话采访. 问:学长你们当时开发项目叫什么名称? 答:我们做的是一个团购业务的APP开发,叫做“团吗” 问:那咱们那个团队当时有多少人员? 答:刚开始的时候有6个人,一段时间后又加入了两个 问:你们开发的软件当时有多少用户,能给用户多少价值?那个APP现在还有人用吗? 答:当时由于力量比较小,找到的商家比较少,所以用户比较少,大约只有一百人左右吧.当时我们的设想就是能让用户在我们平台上能够很方便快捷的购买到自己的想要的业务,能提供比其他平台更

现代软件工程_第一周练习_第5题

你所在的学校有计算机科学专业和软件工程专业么?相关专业的教学计划和毕业出路有什么不同?采访这些不同专业的老师/同学. 如果是计算机系,问老师: 你发现了计算机科学的什么客观规律? 如果是软件工程,问老师:你构建了什么样的软件?你发现了工程的什么规律? 阅读本书有关软件工程和计算机科学的区别的内容,并看其他文章,谈谈你的看法. 文章举例:http://www.drdobbs.com/architectureand-design/software-engineering-computer-scien

现代软件工程_第一周练习_第6题

“刷课机”这类软件能帮助使用软件的人按时快捷的选上他们想选课程,或者帮助他们忙着其他事情的同时就能买得到自己想要的火车票等等,但与此同时也会使那些没有使用这种软件的与自己喜爱的课程失之交臂,或者让那些耗费了好长时间一直盯着买票系统的人们也没能买到适合自己的车票…… 如果我们每个人都使用这类软件来达到我们的目的,大量的请求必定会使服务器崩溃,最终适得其反,并且会对系统所有者造成损失,并且这类软件的出现在很大程度上打破了原来公平竞争的现象,也可以说是使用这类软件的人是“作弊”行为,所以说这类软件不符

现代软件工程_第一周练习_第13题_万世想

1. 原题目: 我们说,软件企业 = 软件 + 商业模式.下面提到的一个游戏团队, 有很好的软件,但是商业模式和其他软件之外的因素呢?有没有考虑到?http://news.cnblogs.com/n/528911/ 2. 我的想法: 关于这个问题,我想先一句话总结一下:游戏这种软件需要:软件+商业模式+营销+社会经济大环境+运气.其中,软件包括:优质的UI.强悍的服务器.调动玩家积极性.易操作等等. 一款游戏如果实现爆发,需要的条件真是太多太多了,以至于在很长一段时间里我都认为是靠运气才能火.举

现代软件工程_第一周练习_第13题

请看TED的演讲, 谈谈你对压力的看法,以及怎么和别人合作, 帮助别人,把压力转化为动力,在互相帮助的环境中成长. 答:“物竞天择,适者生存”是我一直崇尚的一句话.对于压力,我想说因人而异.对于足够强大的人 ,压力会变成动力,对于弱者哪怕一丝压力也会把你打垮.这篇演讲的内容很有趣,最令我印象深 刻的是:根据调查,觉得自己压力很大的人群死亡率并不是很大,而是那些认为压力对人体健康有 害的人群死亡率最高,甚至成了美国死亡原因排名的第十二位,打败了皮肤类癌症.艾滋病等疾病 造成的死亡率.由此可见,打败

现代软件工程_第一周练习_第14题

一:基于Android的HelloWorld程序开发 该程序的开发环境和工具是:AndroidStudio1.5+Android5.1.1版本的手机: 开发流程: 1.File → New → New Project   如图: 2 .如图,输入自己的项目名称:Hello_World,并选择自己项目所在的位置,然后选择“Next” 3.如图选择自己要开发程序所运用的平台,并按自己的需求选择SDK的版本,然后“Next” 4.选择一个默认的Activity模式,然后选择“Next” 如图: 5.给