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

第二次作业

GIT地址 https://github.com/swpuliuchuan
GIT用户名 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的基本操作,下次提交应该会熟练很多。

posted @ 2019-09-18 20:50  swpu刘c  阅读(198)  评论(1编辑  收藏  举报