四则运算修改完善


1、Random处理


在最开始的设计中,每一次调用random.Next()的时候,都是新建的Random random。导致了在运行过程中,每一次结果都有重复的表达式,甚至全部一样,而在自己调试的过程中却发现并不是这样。于是查阅资料以及询问同学,才知道实际运行过程中,因为时间非常短暂,所以造成随机数不随机的情况。

         public expression carryOut(){
                //  Random random = new Random();
                //每一个表达式的每一个数字及符号生成
            int i=0;
            expression e = new expression(signNum);
            while(i<signNum+1){
                i++;
                ifFraction=random.Next(0,2);
                figure f = new figure(ifFraction) 
                          ……
                }
           }

于是将Main函数里的random作为参数传入每一个使用的方法里。

        public Create(int n, int r, Random ra){
          //  Random random = new Random();
            quantity = n;
            maxrange = r;
            random = ra;
            signNum = random.Next(0,4);
            sign.Add('+');
            sign.Add('-');
            sign.Add('*');
            sign.Add('/');
        }        

这样就解决了问题。


2、文件输出


FileStream Answerfile = new FileStream("Answers.txt", FileMode.Create);
StreamWriter A1 = new StreamWriter(Answerfile);

原本在以上定义之后,只需要使用A1.Write()或者A1.WriteLine()即可以将想要输出的内容输入到文件中,但是自己在操作过程中发现打开对应的txt文件时发现里面是空的,同学说write函数在输出过程时可能会发生覆盖情况,导致最后反而没有结果。

于是更改在每个部分都使用Write系列输出,而是选择全部保存在字符串中,通过一个A1.WriteLine(string)输出。

            output = ("Correct: " + right.Count().ToString());
            int i;
            if (right.Count() > 0)
            {

                output += (" (");
                for (i = 0; i < right.Count(); i++)
                {
                    if (i != right.Count() - 1)
                    {
                        output += (right[i].ToString() + ", ");
                        //C1.Write(i + ", ");

                    }
                    else
                    {
                        output += (right[i].ToString() + ")
");
                        //   C1.Write(i + ")
");
                    }
                }
            }
            else
                output += "
";

3、分数判断


在生成分数阶段总是会造成死循环,真分数必须要满足分子和分母没有公约数,分母不为0或1,分子不为0,所以在分子分母都是随机数生成之后判断两者是否有最大公约数,但是却忘记考虑分子为0,分母为0或者1的情况,所以在循环中经常出不来。

                   if(ifFraction==1){
                    // fraction
                     int d = random.Next(1,maxrange+1);
                     int n = random.Next(1,maxrange+1);
                   
                    
                     while(true){
                        if(( n %d!=0)&&(d%n!=0))
                            break;
                        else
                            n = random.Next(1, maxrange + 1);
                    }
                    
                    basic b = new basic();
                    int m = b.gcd(n,d);
                    d = d/m;
                    n = n/m;
                    f.Denominator(d);
                    f.Numerator(n);

于是直接把分子分母的随机数生成范围改成了1-r。


4、计算部分


计算部分选择的是中缀转前缀并且使用前缀表达式计算的算法。

但是因为这一部分代码比较复杂,所以在最开始写的时候有很多没有注意到的问题影响了程序的运行结果,最后在调试的时候才找到这些错误。

(1)乘除

                else if (s == "×")
                {
                    signs.Push('*');
                }
                else if (s == "÷")
                {
                    signs.Push('/');
                }

因为要求是输入输出到文件中的乘除法用×÷代替*和/,所以必须要在读取时将字符转过来,否则无法处理计算。

(2)分数的计算

因为有整数和整数之间的计算,整数和分数之间的计算,分数和分数之间的计算。涉及到加减乘除需要分子分母对应的倍数处理时在最开始写的时候没有很细心,所以忘记了处理。尤其是在分数与分数的加减法时

                        if(c == '+')
                        {
                            //两个分数的加减乘除
                            fenmu = fenmu1 * fenmu2;
                            fenzi = fenmu1 * fenzi2 + fenmu2 * fenzi1;
                        }
                        else if (c == '-')
                        {
                            fenmu = fenmu1 * fenmu2;
                            fenzi = fenmu2 * fenzi1 - fenmu1 * fenzi2;
                        }

在调试的时候才改正回来。

(3)栈的变化

中缀转前缀,最后的结果存储在栈里从栈顶一个个Pop输出就是前缀表达式。

但是前缀表达式计算的时候是从左到右计算的,也就是说,中缀转前缀最终栈与所要求的前缀表达式对应的读取方式正好是相反的。

于是在两个算法链接的地方,加入

            while (signs.Count() != 0)
            {
                stackitem st = new stackitem(0);
                st.setsign(signs.Peek());
                items.Push(st);
                signs.Pop();
            }

(4)……


5、……


以上都属于比较严重的技术上的失误,还有比较小的因为括号或者初始化的问题也都在调试过程中发现的。

从最开始交上去的什么都跑不了,到最后能够正常运行,debug是最必须的。

原文地址:https://www.cnblogs.com/yufisherman/p/4881137.html