个人第2次作业:熟悉使用工具

mac2022-06-30  20

第二次作业

GIT地址https://github.com/swpuliuchuanGIT用户名swpuliuchuan学号后5位24140博客地址https://www.cnblogs.com/swpulc/作业链接https://edu.cnblogs.com/campus/xnsy/GeographicInformationScience/homework/7582

Part1.配置环境

环境:Visual Studio 2017

Part2.克隆项目

1.登录自己的Github,将阿超的四则运算库拷贝到自己的同名仓库中

2.安装Git后克隆项目到本地文件夹D/work2

Part3.程序设计

1.设计思路 流程图 程序的关键是随机生成N道题目和计算结果随机生成N道题目,可以用C#的Random函数来实现,当代码写完的时候才发现这是“伪随机数”,于是百度了一下,借鉴了https://blog.csdn.net/xiaochenXIHUA/article/details/89574431这篇文章,改进了代码。利用Guid生成种子产生了新随机数。随机数既然解决了,再利用switch分支就可以生成题目。计算结果,刚拿到手里几乎是迷茫的,因为题目的括号,运算符号的优先级并不知道如何处理,后来请教了其他同学,可以利用二叉树来实现,例如:**3+2*9-16/4**可以用二叉树形式来表达。 计算过程:“ ”号结点的左右孩子均为数字,可以直接计算,为18,接下来计算“+”,为21,然后计算“/”,为4,最后计算根结点的“-”,最终结果为17。遵循着这个算法可以看出:操作数都是叶子结点,运算符都为内部结点,而且运算符优先级较高的都在下方。知晓了大概的做法后,开始编写代码。

2 代码

获取随机数

static int GetRandomSeed() { byte[] bytes = new byte[4]; System.Security.Cryptography.RNGCryptoServiceProvider rng = new System.Security.Cryptography.RNGCryptoServiceProvider(); rng.GetBytes(bytes); return BitConverter.ToInt32(bytes, 0); } public static char getOperator() { char operator1 = '0'; Random ran = new Random(GetRandomSeed()); int i = ran.Next(4); switch (i) { case 0: operator1 = '+'; break; case 1: operator1 = '-'; break; case 2: operator1 = '*'; break; case 3: operator1 = '/'; break; } return operator1; } /* * 根据范围获取随机数 */ public static int getNumber(int max) { int number = 0; Random ran = new Random(GetRandomSeed()); number = ran.Next(max + 1); return number; } /* * 随机确定子结点 */ public static bool[] getChildPlace(int num) { int d = 0; int size = 0, j = 1; while (num >= (int)Math.Pow(2, j)) { j++; } d = (int)Math.Pow(2, j) - 1 - num; size = (int)Math.Pow(2, j - 1); bool[] k = new bool[size]; for (int i = 0; i < size; i++) { k[i] = true; } for (int i = 0; i < d; i++) { Random ran = new Random(GetRandomSeed()); int f = ran.Next(size); while (k[f] == false) { f = ran.Next(size); } k[f] = false; } return k; } }

计算

/* * 得到运算结果,并检验: * 1.除数为0 * 2.不能整除 * 出现以上两种情况的话将该运算符转换成其他三种运算符 */ public String getResult() { if (hasChild()) { switch (str) { case "+": return (int.Parse(getLchild().getResult()) + int.Parse(getRchild().getResult())).ToString(); case "-": return (int.Parse(getLchild().getResult()) - int.Parse(getRchild().getResult())).ToString(); case "*": return (int.Parse(getLchild().getResult()) * int.Parse(getRchild().getResult())).ToString(); case "/": if (getRchild().getResult().Equals("0")) { while (str.Equals("/")) { str = (Ran.getOperator().ToString()); } return this.getResult(); } else if (int.Parse(getLchild().getResult()) % int.Parse(getRchild().getResult()) != 0) { while (str.Equals("/")) { str = (Ran.getOperator()).ToString(); } return this.getResult(); } else return (int.Parse(getLchild().getResult()) / int.Parse(getRchild().getResult())).ToString(); } } return str; } public String toString() { String Lstr = "", Rstr = "", Str = ""; if (hasChild()) { //判断右子树 if (getRchild().hasChild()) { //判断左邻括号的运算符是否为'/' if (str.Equals("/")) { //获取右子树的表达式 Rstr = getRchild().toString(); } //判断左邻括号的运算符 else if (str.Equals("*") || str.Equals("-")) { //判断op运算符 if (getRchild().str.Equals("+") || getRchild().str.Equals("-")) { Rstr = getRchild().toString(); } else { //获取右子树的表达式 Rstr = getRchild().toString().Substring(1, getRchild().toString().Length - 2); } } else { //去掉括号 Rstr = getRchild().toString().Substring(1, getRchild().toString().Length - 2); } } else { Rstr = getRchild().str; } if (getLchild().hasChild()) { if (str.Equals("*") || str.Equals("/")) { if (getLchild().str.Equals("+") || getLchild().str.Equals("-")) { Lstr = getLchild().toString(); } else { Lstr = getLchild().toString().Substring(1, getLchild().toString().Length - 2); } } else { Lstr = getLchild().toString().Substring(1, getLchild().toString().Length - 2); } } else { Lstr = getLchild().str; } //获取当前的运算式,并加上括号 Str = "(" + Lstr + str + Rstr + ")"; } else { //判断是否有孩子 Str = str; } return Str; } public bool hasChild() { if (lchild == null && rchild == null) return false; else return true; } }

输出到txt文件

FileStream fs = new FileStream(@"D:\Calculator\Output.txt", FileMode.Create); //创建文件流 StreamWriter sw = new StreamWriter(fs); int z; BinaryTree bt; Console.WriteLine("How many questions do u need?"); z = int.Parse(Console.ReadLine()); for (int i = 0; i < z; i++) { bt = new BinaryTree(2); bt.createBTree(); String result = bt.CalAndVal(); Console.WriteLine(bt.ToString() + "=" + result); sw.WriteLine(bt.ToString() + "=" + result); } sw.WriteLine(" Time:" + DateTime.Now.ToString()); //清空缓冲区 sw.Flush(); //关闭文件流 sw.Close(); fs.Close();

结果

Part4.单元测试

新建单元测试

添加引用 单元测试内容,随机生成的符号是否正确

Part5.效能分析

修改主函数 打开效能工具 点击详细报告可以得到代码中每个函数被利用的次数,如果能够减少次数并且达到同样的目的,是可以节约电脑的损耗和时间,这就是优化代码和采用更优算法的结果。 可以看到我所写的生成二叉树的方法,所耗用的时间占到了百分之52(使用了324毫秒的CPU时间),如果能够换个思路来写或者将一些占用时间的外部方法改进,也许能够减少使用CPU时间。

Part6.提交代码

Part7.总结与分享

初次使用Git还是有着诸多的不习惯,主要还是英语太差了,编程的能力也下滑了不少,不过通过这次作业还是学习到了git的基本操作,下次提交应该会熟练很多。

转载于:https://www.cnblogs.com/swpulc/p/11545272.html

最新回复(0)