小学生四则运算应用软件(二)

一、针对上周的程序改进:

(1)除零问题:生成题目的时候同时计算,try catch异常,若有异常则重新生成

测试用例为2/(2-2),如下会产生分母不应为0的异常

这里的FractionException有多种类型,比如分母不能为0、计算时超出数值范围、无法转化为Fraction等。

(2)参数化和用户输入异常处理:

参数化是直接使用C#主函数的String[] args,并且针对每种错误情况都要抛出相应异常,也是使用的try catch机制,其代码如下:

  1  static void Main(string[] args)
  2         {
  3             Console.WriteLine("-n表示生成四则算式的数目");
  4             Console.WriteLine("-a表示用户是否输入答案(1输入,0不输入)");
  5             Console.WriteLine("-c表示是否显示正确答案(1显示,0不显示)");
  6             Console.WriteLine("-t表示是否生成题目文件(1生成,0不生成)");
  7             Console.WriteLine("-m表示文件生成题目的数量(若生成题目文件该参数必须输入,否则不输入)");
  8             try
  9             {
 10                 if (args.Length != 8 && args.Length != 10)
 11                     throw new Exception("参数数目不正确");
 12                 else if (args.Length == 8)
 13                 {
 14                     if (args[0] != "-n" || args[2] != "-a" || args[4] != "-c" || args[6] != "-t")
 15                         throw new Exception("参数名称不正确");
 16                     if (int.Parse(args[1]) <= 0)
 17                         throw new Exception("题目数必须为正");
 18                     if (int.Parse(args[7]) == 1)
 19                         throw new Exception("参数数目不正确");
 20                     if ((int.Parse(args[3]) != 0 && int.Parse(args[3]) != 1) ||
 21                             (int.Parse(args[5]) != 0 && int.Parse(args[5]) != 1))
 22                         throw new Exception("参数值必须为0或1");
 23                 }
 24                 else
 25                 {
 26                     if (args[0] != "-n" || args[2] != "-a" || args[4] != "-c" || args[6] != "-t" || args[8] != "-m")
 27                         throw new Exception("参数名称不正确");
 28                     if (int.Parse(args[1]) <= 0 || int.Parse(args[9]) <= 0)
 29                         throw new Exception("题目数必须为正");
 30                     if (int.Parse(args[7]) == 0)
 31                         throw new Exception("参数数目不正确");
 32                     if ((int.Parse(args[3]) != 0 && int.Parse(args[3]) != 1) ||
 33                             (int.Parse(args[5]) != 0 && int.Parse(args[5]) != 1))
 34                         throw new Exception("参数值必须为0或1");
 35                 }
 36
 37                 int numOfQue = int.Parse(args[1]);
 38                 string[] inputAnswer = new string[numOfQue];
 39                 string[] correctAnswer = new string[numOfQue];
 40                 string[] ques = new string[numOfQue];
 41                 List<string> result = new List<string>();
 42                 for (int i = 0; i < numOfQue; i++)
 43                 {
 44
 45                     result = produceQue();
 46                     ques[i] = result[0];
 47                     try
 48                     {
 49                         correctAnswer[i] = Calculate(result);
 50                         Console.WriteLine("{0,-20}", ques[i] + operators[4] + space);
 51                     }
 52                     catch (FractionException e)
 53                     {
 54                         i--;
 55                     }
 56                 }
 57                 Console.WriteLine();
 58                 int input = int.Parse(args[3]);
 59                 if (input == 1)
 60                 {
 61                     Console.Write("输入答案: ");
 62                     for (int i = 0; i < numOfQue; i++)
 63                     {
 64                         Console.Write("{0,-20}", ques[i] + operators[4] + space);
 65                         inputAnswer[i] = Console.ReadLine();
 66                     }
 67
 68                     int numOfCorrect = 0;
 69                     for (int i = 0; i < numOfQue; i++)
 70                     {
 71                         if (inputAnswer[i] == correctAnswer[i])
 72                             numOfCorrect++;
 73                     }
 74                     Console.WriteLine("您共答对" + numOfCorrect + "道题");
 75                 }
 76                 input = int.Parse(args[5]);
 77                 if (input == 1)
 78                 {
 79                     Console.Write("正确答案: ");
 80                     for (int i = 0; i < numOfQue; i++)
 81                         Console.Write("{0,-20}", ques[i] + operators[4] + space + correctAnswer[i]);
 82                     Console.WriteLine();
 83                 }
 84
 85                 input = int.Parse(args[7]);
 86                 if (input == 1)
 87                 {
 88                     string filename = "que.txt";//这里是你的已知文件
 89                     FileStream fs = File.Create(filename);  //创建文件
 90                     fs.Close();
 91                     StreamWriter sw = new StreamWriter(filename);
 92                     input = int.Parse(args[9]);
 93                     for (int i = 0; i < input; i++)
 94                     {
 95                         string que = "";
 96                         que = produceQue()[0];
 97                         sw.Write("{0,-20}", que + operators[4] + space);
 98                         if (i % 10 == 9)
 99                             sw.Write("\r\n");
100                     }
101                     sw.Close();
102                 }
103             }
104             catch (Exception e)
105             {
106                 Console.WriteLine(e.Message);
107                 Console.WriteLine("请输入正确参数");
108             }
109         }

其中参数说明为:

测试用例及结果如图所示:

这是目前考虑的参数问题,当然我们也可以添加更多的参数,例如生成四则运算表达式运算符的数目以及操作数的范围。

(3)括号交叉重叠的问题:

目前括号的功能是通过随机生成(、)位于第几个操作数来实现,但这样可能会出现这种情况(2*(4)+3)。即第一对括号是(2*4),第二对括号是(4+3),处理的方法是如果同一个操作数前后分别有左括号和右括号,就将这两括号省略不添加。部分代码截图如下:

(4)代码优化及扩展:

由于最后是想将该应用以网页(Java Web)的形式显示,因此检查重复问题、优化等都是在Java程序的基础上改进。目前是已经将程序的主要功能通过Python、Java实现了,那么就浅谈下代码的转变之路。

二、C#转Python---Python功能强大之处

Python编程速度快,有很多强大的第三方库,还可以有负索引独特的语法,无数据类型的严格限制...种种优点促成了Python已然成为了当前社会下十分流行的语言。

简单举个例子,在C#辛辛苦苦写的Fraction类,Python里只需from fractions import Fraction这样一句话就可以搞定(o(╯□╰)o,独自在风中凌乱会儿)。而无数据类型的严格限制,使得我们没必要检查类型转化的错误,甚至可以在一个List里添加多种数据类型的元素。当然负索引的出现,也能让我们直接将List转化成栈和队列的这种结构。再加上Python代码的严格缩进,又会让代码风格整齐美观,这些怎能不令程序猿为之欣喜若狂?废话不多说,直接上代码:

  1 from fractions import Fraction
  2 import random
  3 input0 = 1
  4 operators = "+-*/="
  5 space = " "
  6 priorities = {"#": -1, "+": 0, "-": 0,"*":1,"/":1}
  7 def produceQue():
  8     strque = []
  9     isOperand = []
 10     count = random.randint(1, 2)
 11     num = []
 12     den = []
 13     operand = []
 14     index = []
 15     numOfBrackets = 0
 16     for i in range(count + 1):
 17         num.append(random.randint(2, 4))
 18         if random.randint(1, 10) < 8:
 19             den.append(1)
 20         else:
 21             den.append(random.randint(1, 4))
 22             numOfBrackets = random.randint(1, count)
 23         operand.append(Fraction(num[i], den[i]))
 24         if i < count:
 25             index.append(random.randint(0, 3))
 26     start = []
 27     end = []
 28     for i in range(numOfBrackets):
 29         start.append(random.randint(1, count))
 30         end.append(random.randint(start[i]+1, count + 1))
 31     for i in range(len(start)):
 32         for j in range(len(end)):
 33             if start[i] == end[j]:
 34                 start.pop(i)
 35                 end.pop(j)
 36                 start.append(-1)
 37                 end.append(-1)
 38     j = 1
 39     for i in range(count + 1):
 40         strque.append(str(operand[i]))
 41         isOperand.append(i + 1)
 42         if i < count:
 43             strque.append(operators[index[i]])
 44             isOperand.append(0)
 45     for i in range(numOfBrackets):
 46         if start[i] != -1:
 47           left = isOperand.index(start[i])
 48           strque.insert(left, "(")
 49           isOperand.insert(left, -1)
 50         if end[i] != -1:
 51           right = isOperand.index(end[i])
 52           strque.insert(right+1, ")")
 53           isOperand.insert(right+1, -1)
 54     strque.insert(0, "")
 55     j = 1
 56     while j < len(strque):
 57         strque[0] += strque[j] + space
 58         j = j + 1
 59     return strque
 60
 61 def Compute(leftNum,rightNum,op):
 62     if op == 0:
 63         return Fraction(leftNum)+Fraction(rightNum)
 64     if op == 1:
 65         return Fraction(leftNum)-Fraction(rightNum)
 66     if op == 2:
 67         return Fraction(leftNum)*Fraction(rightNum)
 68     if op == 3:
 69         return Fraction(leftNum)/Fraction(rightNum)
 70
 71 def IsOperator(op):
 72     try:
 73         i = operators.index(str(op))
 74         bo = True
 75     except:
 76         bo = False
 77     finally:
 78         return bo
 79
 80 def IsLeftAssoc(op):
 81     if op == "+" or op == "-" or op == "*" or op == "/":
 82         return True
 83     else:
 84         return False
 85
 86
 87 def PreOrderToPostOrder(expression):
 88     result = []
 89     operatorStack = []
 90     operatorStack.append("#")
 91     top = ""
 92     cur = ""
 93     tempChar = ""
 94     tempNum = ""
 95     i = 1
 96     while i < len(expression):
 97         cur = expression[i]
 98         top = operatorStack[-1]
 99         if cur == "(":
100             operatorStack.append(cur)
101         else:
102             if(IsOperator(cur)):
103                 while IsOperator(top) and (IsLeftAssoc(cur) and priorities[cur] <= priorities[top]) or (not IsLeftAssoc(cur) and priorities[cur] < priorities[top]):
104                    result.append(operatorStack.pop())
105                    top = operatorStack[-1]
106                 operatorStack.append(cur)
107             elif cur == ")":
108                 tempChar = operatorStack.pop()
109                 while len(operatorStack) > 0 and   tempChar != "(":
110                     result.append(tempChar)
111                     tempChar = operatorStack.pop()
112             else:
113                 tempNum = cur
114                 result.append(tempNum)
115         i = i + 1
116
117     while len(operatorStack) > 0:
118         cur = operatorStack.pop()
119         if cur == "#":
120             continue;
121         if len(operatorStack) > 0:
122             top = operatorStack[-1]
123         result.append(cur)
124     return result
125
126 def Calculate(expression):
127     rpn = PreOrderToPostOrder(expression)
128     operandStack = []
129     left = ""
130     right = ""
131     while len(rpn) > 0:
132         cur = rpn.pop(0)
133         if IsOperator(cur):
134             right = operandStack.pop()
135             left = operandStack.pop()
136             index = operators.index(cur)
137             operandStack.append(Compute(left,right,index))
138         else:
139             operandStack.append(cur)
140     return operandStack.pop()
141
142 while input0 == 1:
143     print("请输入生成四则运算题的数目:")
144     numOfQue = int(input())
145     inputAnswer = []
146     correctAnswer = []
147     ques = []
148     result =[]
149     for i in range(numOfQue):
150        result = produceQue()
151        ques.append(result[0])                       print(result[0]+space+operators[4]+space+str(Calculate(result)))

测试用例如下:

三、C#转Java---一切只为了网页显示

很不幸Java也没有Fraction类,那就自己写呗,主要功能实现如下:

  1 public class Fraction {
  2         long m_iNumerator;
  3         long m_iDenominator;
  4
  5
  6         public Fraction() throws Exception
  7         {
  8             Initialize(0,1);
  9         }
 10
 11         public Fraction(long iWholeNumber) throws Exception
 12         {
 13             Initialize(iWholeNumber, 1);
 14         }
 15
 16         public Fraction(String strValue) throws Exception
 17         {
 18             Fraction temp=ToFraction(strValue);
 19             Initialize(temp.getNumerator(), temp.getDenominator());
 20         }
 21
 22         public Fraction(long iNumerator, long iDenominator) throws Exception
 23         {
 24             Initialize(iNumerator, iDenominator);
 25         }
 26         private void Initialize(long iNumerator, long iDenominator) throws Exception
 27         {
 28             this.setNumerator(iNumerator);
 29             this.setDenominator(iDenominator);
 30             ReduceFraction(this);
 31         }
 32
 33
 34
 35         public long getNumerator()
 36         {
 37             return m_iNumerator;
 38         }
 39         public void setNumerator(long Numerator)
 40         {
 41             m_iNumerator = Numerator;
 42         }
 43         public long getDenominator() throws Exception
 44         {
 45             if(m_iDenominator != 0)
 46               return m_iDenominator;
 47             else
 48                 throw new Exception("Denominator cannot be assigned a ZERO Value");
 49         }
 50         public void setDenominator(long Denominator) throws Exception
 51         {
 52             if(Denominator != 0)
 53              m_iDenominator = Denominator;
 54             else
 55                 throw new Exception("Denominator cannot be assigned a ZERO Value");
 56         }
 57
 58
 59
 60
 61         public String ToString() throws Exception
 62         {
 63             String str;
 64             if ( this.getDenominator()==1 )
 65                 str=Long.toString(this.getNumerator());
 66             else
 67                 str=this.getNumerator() + "/" + this.getDenominator();
 68             return str;
 69         }
 70
 71         public static Fraction ToFraction(String strValue) throws Exception
 72         {
 73             int i;
 74             for (i=0;i<strValue.length();i++)
 75                 if (strValue.charAt(i)==‘/‘)
 76                     break;
 77
 78             if (i==strValue.length())
 79                 return new Fraction(Long.parseLong(strValue),1);
 80
 81             long iNumerator=Long.parseLong(strValue.substring(0,i));
 82             long iDenominator=Long.parseLong(strValue.substring(i+1));
 83             return new Fraction(iNumerator, iDenominator);
 84         }
 85
 86         public static void ReduceFraction(Fraction frac) throws Exception
 87         {
 88             try
 89             {
 90                 if (frac.getNumerator()==0)
 91                 {
 92                     frac.setDenominator(1);
 93                     return;
 94                 }
 95
 96                 long iGCD=GCD(frac.getNumerator(), frac.getDenominator());
 97                 frac.setNumerator(frac.getNumerator()/iGCD);
 98                 frac.setDenominator(frac.getDenominator()/iGCD);
 99
100                 if ( frac.getDenominator()<0 )
101                 {
102                     frac.setNumerator(frac.getNumerator()*(-1));
103                     frac.setDenominator(frac.getDenominator()*(-1));
104                 }
105             }
106             catch(Exception exp)
107             {
108                 throw new Exception("Cannot reduce Fraction: " + exp.getMessage());
109             }
110         }
111         private static long GCD(long iNo1, long iNo2)
112         {
113
114             if (iNo1 < 0) iNo1 = -iNo1;
115             if (iNo2 < 0) iNo2 = -iNo2;
116
117             do
118             {
119                 if (iNo1 < iNo2)
120                 {
121                     long tmp = iNo1;
122                     iNo1 = iNo2;
123                     iNo2 = tmp;
124                 }
125                 iNo1 = iNo1 % iNo2;
126             } while (iNo1 != 0);
127             return iNo2;
128         }
129
130         public static Fraction Inverse(Fraction frac1) throws Exception
131         {
132             if (frac1.getNumerator()==0)
133                 throw new Exception("Operation not possible (Denominator cannot be assigned a ZERO Value)");
134             long iNumerator=frac1.getDenominator();
135             long iDenominator=frac1.getNumerator();
136             return ( new Fraction(iNumerator, iDenominator));
137         }
138
139         public String Add(String str1, String str2)
140         {
141
142             try{
143               Fraction frac1 = new Fraction(str1);
144               Fraction frac2 = new Fraction(str2);
145               long iNumerator=frac1.getNumerator()*frac2.getDenominator() + frac2.getNumerator()*frac1.getDenominator();
146               long iDenominator=frac1.getDenominator()*frac2.getDenominator();
147               return ( new Fraction(iNumerator, iDenominator).ToString() );
148             }catch(Exception e){
149                 return e.getMessage();
150             }
151         }
152
153         public String Multiply(String str1, String str2)
154         {
155             try{
156               Fraction frac1 = new Fraction(str1);
157               Fraction frac2 = new Fraction(str2);
158               long iNumerator=frac1.getNumerator()*frac2.getNumerator();
159                 long iDenominator=frac1.getDenominator()*frac2.getDenominator();
160               return ( new Fraction(iNumerator, iDenominator).ToString() );
161             }catch(Exception e){
162                 return e.getMessage();
163             }
164         }
165 }

主函数代码为:

  1 import java.util.ArrayList;
  2 import java.util.HashMap;
  3 import java.util.LinkedList;
  4 import java.util.Queue;
  5 import java.util.Random;
  6 import java.util.Scanner;
  7 import java.util.Stack;
  8
  9 public class Program{
 10
 11     static Random ran = new Random();
 12     static HashMap<String, String> priorities = new HashMap<String, String>() {
 13         {
 14             put("#", "-1");
 15             put("+", "0");
 16             put("-", "0");
 17             put("*", "1");
 18             put("/", "1");
 19         }
 20     };
 21     final static String operators = "+-*/=";
 22     final static String space = " ";
 23
 24   public static void main(String args[]) throws Exception{
 25       int input = 1;
 26       while (input == 1)
 27       {
 28           System.out.println("请输入生成四则运算题的数目: ");
 29           Scanner sc = new Scanner(System.in);
 30           int numOfQue = sc.nextInt();
 31           String[] ques = new String[numOfQue];
 32           ArrayList que = new ArrayList();
 33
 34           for(int i = 0;i < numOfQue;i++){
 35               que = produceQue();
 36               ques[i] = (String) que.get(0);
 37               TreeNode s = suffixExpressionToTree(PreOrderToPostOrder(que));
 38               System.out.println();
 39               System.out.println(ques[i] + operators.charAt(4) + space + Calculate(que));
 40
 41           }
 42       }
 43 }
 44   static ArrayList produceQue() throws Exception{
 45       ArrayList str = new ArrayList();
 46       ArrayList isOperand = new ArrayList();
 47       int count = ran.nextInt(2) + 1;
 48       int[] num = new int[count+1];
 49       int[] den = new int[count+1];
 50       String[] operand = new String[count+1];
 51       int[] index = new int[count];
 52       int numOfBrackets = 0;
 53       if(count > 1)
 54           numOfBrackets = ran.nextInt(count);
 55       for(int i = 0;i < count + 1;i++){
 56           num[i] = ran.nextInt(3) + 2;
 57           if(ran.nextInt(10) < 8)
 58               den[i] = 1;
 59           else{
 60               den[i] = ran.nextInt(4)+1;
 61           }
 62           operand[i] = new Fraction(num[i],den[i]).ToString();
 63           if(i < count)
 64               index[i] = ran.nextInt(4);
 65       }
 66       ArrayList start = new ArrayList(numOfBrackets);
 67       ArrayList end = new ArrayList(numOfBrackets);
 68       for(int i = 0;i < numOfBrackets;i++){
 69            start.add(ran.nextInt(count-1) + 1);
 70            end.add(ran.nextInt(count-(int)start.get(i)) + (int)start.get(i) + 1);
 71       }
 72       for(int i = 0;i < numOfBrackets;i++)
 73           for(int j = 0;j < numOfBrackets;j++){
 74               if(start.get(i).equals(end.get(j))){
 75                   start.set(i, -1);
 76                   end.set(j, -1);
 77               }
 78           }
 79       for(int i = 0;i < count + 1;i++){
 80           str.add(operand[i]);
 81           isOperand.add(i + 1);
 82           if(i < count){
 83               str.add(operators.charAt(index[i]));
 84               isOperand.add(0);
 85           }
 86       }
 87      for(int i = 0;i < numOfBrackets;i++){
 88          if((int)start.get(i) != -1){
 89              int left = isOperand.indexOf(start.get(i));
 90              str.add(left, "(");
 91              isOperand.add(left,0);
 92          }
 93          if((int)end.get(i) != -1){
 94              int right = isOperand.indexOf(end.get(i))+1;
 95              str.add(right,")");
 96              isOperand.add(right,0);
 97          }
 98      }
 99      str.add(0,"");
100      int j = 1;
101      while(j < str.size()){
102          str.set(0, str.get(0).toString()+str.get(j).toString()+space);
103          j = j + 1;
104      }
105      return str;
106   }
107   static boolean IsOperator(String op){
108       return operators.contains(op);
109   }
110   static boolean IsLeftAssoc(String op){
111       if(op.equals("+") || op.equals("-") || op.equals("*") || op.equals("/"))
112           return true;
113       else
114           return false;
115   }
116   static String Compute(String leftNum,String rightNum,int op) throws Exception{
117       Fraction result = new Fraction();
118     switch(op){
119     case 0:
120           return result.Add(leftNum,rightNum);
121     case 1:
122           rightNum = "-"+rightNum;
123           return result.Add(leftNum,rightNum);
124     case 2:
125           return result.Multiply(leftNum, rightNum);
126     case 3:
127           rightNum = result.Inverse(new Fraction(rightNum)).ToString();
128           return result.Multiply(leftNum, rightNum);
129       }
130     return null;
131   }
132   static Queue PreOrderToPostOrder(ArrayList expression){
133       Queue<String> result=new LinkedList<String>();
134       Stack<String> operatorStack=new Stack<String>();
135       operatorStack.push("#");
136       String top,cur,tempChar,tempNum;
137       for(int i = 1;i < expression.size();i++){
138           cur =  expression.get(i).toString();
139           top = operatorStack.peek();
140           if(cur == "(")
141               operatorStack.push(cur);
142           else{
143               if(IsOperator(cur)){
144                   while(IsOperator(top) && ((IsLeftAssoc(cur) && priorities.get(cur).compareTo(priorities.get(top))<=0)
145                     ||(!IsLeftAssoc(cur) && priorities.get(cur).compareTo(priorities.get(top)) < 0))){
146                       result.add(operatorStack.pop());
147                       top = operatorStack.peek();
148                   }
149                   operatorStack.push(cur);
150               }
151               else if(cur == ")"){
152                   while(operatorStack.size() > 0 && (tempChar = operatorStack.pop()) != "("){
153                       result.add(tempChar);
154                   }
155               }
156               else{
157                   tempNum = cur;
158                   result.add(tempNum);
159               }
160           }
161       }
162       while(operatorStack.size()>0){
163           cur = operatorStack.pop();
164           if(cur == "#") continue;
165           if(operatorStack.size() > 0)
166               top = operatorStack.peek();
167           result.add(cur);
168       }
169       return result;
170   }
171
172   static String Calculate(ArrayList expression) throws Exception
173   {
174       Queue rpn = PreOrderToPostOrder(expression);
175       Stack operandStack = new Stack<String>();
176       String left, right,cur;
177       while (rpn.size() > 0)
178       {
179           cur = (String) rpn.poll();
180           int index = operators.indexOf(cur);
181           if (index >= 0)
182           {
183               right = (String) operandStack.pop();
184               left = (String) operandStack.pop();
185               operandStack.push(Compute(left, right, index));
186           }
187           else
188           {
189               operandStack.push(cur);
190           }
191       }
192       return (String) operandStack.pop();
193   }
194   static TreeNode suffixExpressionToTree(Queue suffixStr)
195   {
196       if (suffixStr.isEmpty()) return null;
197       // 用于临时存储节点的栈
198       Object[] chs = suffixStr.toArray();
199       Stack<TreeNode> stack = new Stack<TreeNode>();
200       // 遍历所有字符,不是运算符的入栈,是运算符的,将栈中两个节点取出,合成一颗树然后入栈
201       for (int i = 0; i < chs.length; i++)
202       {
203           if (IsOperator(chs[i].toString()))
204           {
205               if (stack.isEmpty() || stack.size() < 2)
206               {
207                   System.err.println("输入的后缀表达式不正确");
208                   return null;
209               }
210               TreeNode root = new TreeNode(chs[i]);
211               root.right = stack.pop();
212               root.left = stack.pop();
213               stack.push(root);
214           }
215           else
216           {
217               stack.push(new TreeNode(chs[i]));
218           }
219       }
220       if (stack.isEmpty() || stack.size() > 1)
221       {
222           System.err.println("输入的后缀表达式不正确");
223           return null;
224       }
225       //stack.pop().printAll();
226        return stack.pop();
227
228   }
229   static boolean CompTree(TreeNode tree1,TreeNode tree2)
230   {
231       if(tree1 == null && tree2 == null)
232           return true;
233
234       if(tree1 != null && tree2 != null)
235       {
236           if(tree1.val.equals(tree2.val))
237           {
238             if(tree1.val.equals("+") || tree1.val.equals("*"))
239             {
240                 if(CompTree(tree1.left, tree2.left) &&
241                   CompTree(tree1.right, tree2.right) ||
242                   CompTree(tree1.right, tree2.left) &&
243                   CompTree(tree1.left, tree2.right))
244               {
245                   return true;
246               }
247           }
248           else{
249                if(CompTree(tree1.left, tree2.left) && CompTree(tree1.right, tree2.right))
250                     {
251                         return true;
252                     }
253           }
254           }
255       }
256       return false;
257   }
258 }

测试用例如下:

这里着重讲下关于生成题目的重复检测问题,刚开始我想着是把四则运算表达式转化成一棵二叉树,那么这就归结成二叉树同构的问题了。函数suffixExpressionToTree便是通过算式后缀式生成一棵二叉树。网上根据http://blog.csdn.net/smartxxyx/article/details/23992487,也请教了一个算法大神,说是要用到哈希。具体策略为:先随机产生一系列随机数作为存到数组,接着从根节点出发,递归计算每个子树的哈希值,将子树的哈希值相加然后和父节点自己对应的数组上的随机数相加得到父节点的哈希值。这个计算结果和子树的顺序是没有关系的,所以同构的树一哈希值一定是一样的。对于异构的树,必然在某些节点计算的哈希值不同,由于都是随机产生的一些数字,因而他们相加值和另外一棵树哈希值相同的概率也会非常低。在"国家集训队2007论文集1.杨弋《Hash在信息学竞赛中的一类应用》.doc"一文中,是使用一种类似树状递推的方法计算二叉树的Hash值,

对于一个节点v,先求出它所有儿子节点的Hash值,并从小到大排序,记作H1H2,…,HD。那么v的Hash值就可以计算为:

换句话说,就是从某个常数开始,每次乘以p,和一个元素异或,再除以q取余,再乘以p,和下一个元素异或,除以q取余……一直进行到最后一个元素为止。最后把所得到的结果乘以b,再对q取余。

+_+那么这样构造的算式二叉树,叶子节点肯定都是操作数,那么Hash值直接取操作数,而后随机a、p、b计算二叉树根的Hash值进行比较。代码实现起来我还是一脸懵逼,如果有谁有这方面的见解,欢迎指教!

现在我只是使用简单粗暴的方式来比较两棵二叉树,就是递归比较他们的左右孩子是否相同,如果节点为"+"或"*",还要互换左右孩子进行比较。

部分测试用例如下:

          

四、总结

整个代码转化比较痛苦,毕竟疏通路是个艰难的过程。而在转化的时候不得不考虑各种语言的特性,可能一种简单的数据结构在另一种语言并没有实现,而复杂的却已封装好,不过这也许就是程序语言的魅力之处了。接下来的工作就是网页显示和细节优化了,敬请期待!

时间: 2024-10-11 10:57:31

小学生四则运算应用软件(二)的相关文章

小学生四则运算应用软件(一)

一.基本想法 (1)整数和分数的四则运算 由于四则运算要支持分数,刚开始我想着是自定义分数这种数据类型,而后再重载运算符.可当整数和分数混合运算的话,就要考虑到数据类型间的转化,比较麻烦.于是我转化了下思路,即将整数看成是特殊的分数(分母为1),这样将整数和分数统一起来,那么初始化便可以根据具体的数据类型做出调整,如下图所示: 这里需要特别注意的是,我们最后控制台显示的算式是String类型,因而要能实现分数Fraction和String直接的相互转化. 而且要自定义一种隐式转化,这样就能令分数

201571030316/201571030314《小学生四则运算练习软件》结对项目报告

github代码地址:https://github.com/mqqgd/Experiment2 小伙伴儿的博客地址链接:http://www.cnblogs.com/mjuan/p/8715700.html 我的学号:201571030316                  小伴儿的学号:201571030314 一.需求分析    本次实验采用结对编程方式,设计开发一个小学生四则运算练习软件,使之具有以下功能: 由计算机从题库文件中随机选择20道加减乘除混合算式,用户输入算式答案,程序检查答

201571030314《小学生四则运算练习软件》结对项目

结对编程实现小学生四则运算练习软件 前言:按照结对编程的原则,我和邻宿舍的小伙伴进行了两人结对编程,我们开发的结对项目的是小学生四则运算练习软件,具体就是随机生成n道题,供学生答题并返回正误记录答题结果,进行多轮.具体需求分析以及功能设计与实现如下. github代码地址:https://github.com/mqqgd/Experiment2 一.需求分析 本次实验采用结对编程方式,设计开发一个小学生四则运算练习软件,使之具有以下功能: 由计算机从题库文件中随机选择20道加减乘除混合算式,用户

201571030134/201571030139《小学生四则运算练习软件需求说明》结对项目报告

任务一 首先,我们进行了用户体验,把我们已经完成的小学生四则运算软件发给我们要调研的人,他们体验了我们的程序后再填写需求分析调查问卷,这样可以更好的得到一个反馈,让我们的需求分析更加清楚. 其次,我们主要采取了精准的调查问卷来进行需求分析,调查对象主要为西北师大附属小学的二至六年级的小学生.师大附小的一些有经验的老师以及我们学院的一些孩子正在上小学的老师.这一点我们是主要考虑到: 大范围的发放调查问卷,填写人员职业和经验都有不确定性,所以不能作为有效的需求分析,所以我们采用了精准问卷调查,让我们

小学生四则运算

package yun; import java.util.Random; import java.util.*; public class number { /** * 作者:范铭祥 * 功能:一个简单的小学生四则运算生成系统 */ public static void main(String[] args) { int max=4; int min=1; Random random = new Random(); //System.out.println(s); boolean pan=tr

自动生成小学生四则运算(C语言)

我写的这个自动生成小学生四则运算的代码是根据我在百度上看到的一篇博客改的,地址为http://www.cnblogs.com/ys1101/p/4368103.html.它的功能不够完整,只有整数的加.减.乘.除,我在此基础上增加了真分数的加.减.乘.除,及统计分数.我把我写的代码放在了GitHub上,地址为https://github.com/cygoodboy/helloworld.

自动生成小学生四则运算(皮!)

自动生成小学生四则运算(皮!) coding 地址 https://coding.net/u/smile12231/p/Demo/git a·需求分析 在这个家长希望自己的小孩能够赢在起跑线的社会,通常寻找很多的练习给小学生做,所以我们就来编写一个四则运算的软件,你懂我意思吧!这个软件能够 ①丶根据用户想要的出题量生成题目 ②丶生成的题目包括整数和分数的加减乘除 ③丶能够自动判断答案是否正确并给出此次的正确率 ④丶使用 -n 参数控制生成题目的个数,例如执行下面命令将生成10个题目 b丶功能设计

安卓小学生四则运算

安卓Activity: package com.example.count_number; import android.os.Bundle;import android.app.Activity;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText; public class MainActivit

【小学生四则运算】程序第3次冲刺(结项成果发布)

茅山光大大组员:林庆光.卢盛添.黄雄俊.陈梓仪.经过三个阶段的协作努力.通力合作,[小学生四则运算]APP程序已经实现了当初设想的全部功能:用户注册与登录(包括找回密码,记住密码功能),用户注册完成同时成为一个游戏账号(可以进行升级,增加金币功能),其中,程序的核心功能包括加法.减法.乘法.除法.以及混合运算的练习题. APP截图展示: 注册界面 登录界面 首页功能展示 答题界面 答题提示框 显示用户信息 商城金币系统 目前APP的功能已经基本定型,接下来就按照杜老师的要求,尝试对APP进行推广