首页 > 代码库 > 四则运算三

四则运算三

  上次的作业,四则运算三,在以前的基础上又有了新的需求。算术题目中不能产生复数,也就是所算术表达式如果有形如e1-e2的子表达式,那么e1>e2 。而且除法的结果可以表示为真分数或者带分数,每道题目不超过三个运算符。而且一次程序运行的结果不能产生重复的表达式,即任何两道题目不能通过有限次的加法交换和乘法交换变成统一到题目(其实我觉得如果两个表达式需要经过加法交换或者乘法交换变成同一道题,那么这两个题也不是重复的题目呀,因为这还需要涉及到交换律呀!)。最重要的是需要连接数据库,计算答案和判定对错。

程序设计思路

  首先要考虑的问题是程序中生成的表达式应该存放在什么地方。就我看来不外乎两种方式,数组和字符串。我选择了字符串,因为在我看来,如果用数组存放不方便括号的处理(也许其他同学有办法,而且觉得数组好)。然后,因为如果有除法运算,结果需要表示为真分数或者带分数形式的字符串,所以在运算过程中必定会牵涉到有分数参与的计算。为了解决这个问题,需要用到分数类,这个类java中似乎没有提供(也许提供了我不知道),所以我自己编写了一个分数类,这个类需要拥有分数的加减乘除功能、比较大小功能等等。其实这一步我在四则运算二的任务重就已经完成了,只是有一点需要重新考虑,在表达式中假分数需要表示为带分数形式,这只需要重新编写toString()方法就行了。另外一个小问题(对我来说也是一个关键问题,解决这个问题候就解决了问题的一半),如何分辨表达式中的除号和分数的分数线。可能有人会说分数线和除号不都是一个意义吗?是的,分数线和除法符号在数学上就是一个意思,但是如果表达式中出现两个连续的除号(除号都用‘/’)例如a/b/c,那么究竟是a除以b除以c呢,还是a除以c分之b呢?老师要求在运算符和操作数之间留有空格,用来区分以上情况,但是这样求值会很困难,因为我是先构建表达式存放在字符串中,然后再求值。及反思所我还是想到了一个好办法 ,用标准的四则运算符号表示运算(﹢﹣×÷)表示即可,反正这只是在字符串中的一个表现形式,不需要程序识别这些运算符。至于在程序中怎么输入这些符号,其实也简单,搜狗输入法可以输入一些特殊的字符。然后是程序的主体部分,求值。其实表达式求值没有什么难的,就是应用堆栈将中缀表达式化为后缀表达式,这些在数据结构中都学过。最后一个难题,怎么比较两个表达式是否重复。我想了很久还是想出来一个方法,这里我把算法列出来。设l1,l2是两个表达式。

  1. 如果l1,l2的值不相同,程序结束,返回false。
  2. 如果l1,l2的字符串相同,及表达式为一模一样,程序结束,返回true
  3. 如果l1,l2的值不相同且字符串不相同,这时我们要判断是否可以经过有限次加法或乘法交换得到相同的表达式。执行以下步骤:

      (1)     如果l1,l2的操作数个数不相同,返回false,程序结束。

      (2)     如果l1,l2的操作数个数相同且都为2,我们便可以方便的判断出这两个表达式是否相同。

      (3)     如果l1,l2的操作数个数相同而且不为2,执行以下步骤:

      1)         取l1,l2中最先运算的子表达式e1,e2.

      2)         递归调用本算法比较e1,e2是否相同。

      3)         如果e1,e2不相同,返回false,程序结束。

      4)         如果e1,e2不相同,用e1,e2的结果替代原表达式中的e1,e2得到两个新的表达式n1,n2。递归调用本方法比较n1,n2是否相同,相同返回true,不相同返回false。

    上面这个算法步骤比较复杂,其中还用到一些其他的步骤,比如如何取出表达式中最先运算的子表达式,如果计算表达式中操作数的个数等。这些都不是简单事。

 

程序代码

  1 import java.util.ArrayList;
  2 import java.util.Scanner;
  3 //import java.util.Scanner;
  4 
  5 public class Equation {
  6 
  7     public static void main(String[] args) throws Exception {
  8         // TODO Auto-generated method stub
  9         Scanner scan = new Scanner(System.in);
 10         boolean flag = false;
 11         boolean ismul = false;
 12         boolean withbrackets = false;
 13         int num = 0;
 14         int sum = 0;
 15         int zhen = 0;
 16         int fenzi = 0;
 17         int fenmu = 0;
 18         
 19         do{
 20             try{
 21                 System.out.println("您需要多少个式子:");
 22                 num = scan.nextInt();
 23                 System.out.println("是否含有乘除法?(true/false)");
 24                 ismul = scan.nextBoolean();
 25                 System.out.println("操作数的个数:");
 26                 sum = scan.nextInt();
 27                 System.out.println("整数最大值:");
 28                 zhen = scan.nextInt();
 29                 System.out.println("分子最大值:");
 30                 fenzi = scan.nextInt();
 31                 System.out.println("分母最大值:");
 32                 fenmu = scan.nextInt();
 33                 System.out.println("是否包含括号:(true/false)");
 34                 withbrackets = scan.nextBoolean();scan.nextLine();
 35                 flag = false;
 36                 int[] correct = new int[num];
 37                 int[] wrong = new int[num];
 38                 int correctsum = 0;
 39                 int wrongsum = 0;
 40                 for(int index  = 0;index<num; index++)
 41                 {
 42                     Equation s = new Equation(ismul,sum,zhen,fenzi,fenmu,withbrackets);
 43                     System.out.print((index+1)+":\t"+s.express +" = ");
 44                     String aws = scan.nextLine();
 45                     if(aws.equals(s.value)){
 46                         correct[correctsum++] = index+1;
 47                     }else{
 48                         wrong[wrongsum++] = index+1;
 49                     }
 50                 }
 51                 if(correctsum>0)
 52                 {
 53                     System.out.print("正确"+correctsum+" correct(");
 54                     for(int j = 0; j < correctsum; j++){
 55                         System.out.print(correct[j]);
 56                         if(j!=correctsum-1)
 57                             System.out.print(",");
 58                         else
 59                             System.out.println(")");
 60                     }
 61                 }
 62                 if(wrongsum>0)
 63                 {
 64                     System.out.print("错误"+wrongsum+" wrong(");
 65                     for(int j = 0; j < wrongsum; j++){
 66                         System.out.print(wrong[j]);
 67                         if(j!=wrongsum-1)
 68                             System.out.print(",");
 69                         else
 70                             System.out.println(")");
 71                     }
 72                 }
 73             }catch(Exception e){
 74                 System.out.println("输入错误,请重新输入!");
 75                 flag = true;
 76             }
 77         }while(flag);
 78         scan.close();
 96     }
 97 
 98     
 99 
100     private String     express,//表达式
101                     value;//表达式结果
102     private int        number;//操作数个数
103     public Equation(boolean incmul,int much,int zhen,int fenzi,int fenmu,boolean withbrackets)
104     {//incmul是否包含乘除法,much表示操作数的个数
105         if(much < 2)
106             much = 2;
107         number = much;
108         boolean tag = false;
109         do{
110             try {
111                 express = createExpress(incmul,much,zhen,fenzi,fenmu,withbrackets);
112                 value   =http://www.mamicode.com/ evaluation(express);
113                 tag = false;
114             } catch (Exception e) {
115                 tag = true;
116             }
117         }while(tag);
118     }
119     public Equation(){
120         this(true,4,100,10,11,true);
121     }
122     public Equation(String exp){
123             express = exp;
124             try {
125                 this.value =http://www.mamicode.com/ evaluation(exp);
126                 this.number= this.allFigure().length;
127             } catch (Exception e) {
128                 this.express = null;
129                 this.value = http://www.mamicode.com/null;
130             }
131     }
132     //setter and get
133     public String getExpress(){return express;}    
134     public void setExpress(String ex){express = ex;}
135     public String getValue(){return value;}
136     public int getNumbers(){return number;}
137     public void setNumber(int n){number = n;}
138     public String toString(){    
139             return express+" = "+value;
140     }    
141     public boolean equals(Equation another)//比较两个算式是否相同
142     {
143         if(this.express==null||this.value=http://www.mamicode.com/=null||another.express==null||another.value=http://www.mamicode.com/=null)
144             return false;
145         //如果两个等式的表达式相同
146         if(this.express.equals(another.express))
147             return true;
148         //如果两个表达式的值不相同,则程序结束
149         if(!getValue().equals(another.getValue()))
150             return false;
151         else{
152             //将表达式分解成数字串和操作符,TODO 如果表达式中没有空格将不能分开
153             String[] part1 = this.separateAll();
154             String[] part2 = another.separateAll();
155             int len1 = part1.length;
156             int len2 = part2.length;
157             //如果分开后的数组长度小于3,则程序出现异常,返回false
158             if(len1<3||len2<3)
159                 return false;
160             //如果两个数组长度不相等,则原表达式不相等
161             if(len1!=len2)
162                 return false;
163             //否则
164             else{
165                 //如果表达式包含一个操作符和两个操作数
166                 if(len1==3){
167                     //如果两个表达式的操作数对应相同
168                     if((part1[0].equals(part2[0])&&part1[2].equals(part2[2])))
169                     {
170                         if(part1[1].equals(part2[1]))
171                             return true;
172                         else 
173                             return false;
174                     }
175                     //如果两个表达式的操作数交叉相同
176                     else if(part1[0].equals(part2[2])&&part1[2].equals(part2[0]))
177                     {
178                         //如果两个表达式的操作符不相同
179                         if(!part1[1].equals(part2[1]))
180                             return false;
181                         //操作符相同
182                         else{
183                             //如果是加法或者乘法
184                             if(part1[1].equals("﹢")||part1[1].equals("×"))
185                                 return true;
186                             //如果是减法或者除法
187                             else
188                                 return false;
189                         }
190                     }
191                     //如果表达式的操作数不相同
192                     else
193                         return false;
194                 }
195                 //如果表达式操作符个数大于一且操作数大于二
196                 else{
197                     //取两个表达式中优先级最高的子表达式
198                     Equation e1 = this.precede();
199                     Equation e2 = another.precede();
200                     //比较两个子表达式是否相同
201                     boolean tag = e1.equals(e2);
202                     //如果子表达式不相同
203                     if(!tag)
204                         return tag;
205                     //如果子表达式相同
206                     else{
207                         //用子表达式的值取代子表达式在原式中的位置,构成新的两个表达式。
208                         String newstr1 = this.express.replaceFirst(e1.express, e1.value);
209                         newstr1 = removeBracket(newstr1,e1.value);//处理一个数由一对括号包围的情况
210                         String newstr2 = another.express.replaceFirst(e2.express, e2.value);
211                         newstr2 = removeBracket(newstr2,e1.value);//处理一个数由一对括号包围的情况
212                         e1 = new Equation(newstr1);
213                         e2 = new Equation(newstr2);
214                         //比较两个新的表达式是否相同,且返回比较结果。
215                         return e1.equals(e2);
216                     }
217                 }
218             }
219         }
220     }
221     /**
222      * 2017/3/19日增加removeBracket()方法
223      * 在去优先级最高的子表达式时,有可能子表达式被一对括号包含,但通过precede
224      * 方法取得的子表达式不含有括号。在equals方法中,用子表达式的值取代子表达式后
225      * 有可能出现一个数带有一个括号,该方法就是去掉这种情况
226      * */
227     private static String removeBracket(String orign,String subvalue)//去掉包含单个数字的括号。
228     {//orign 是原来的表达式字符串形式被自表达式的值取代后的字符串,subvalue为子表达式的值
229         String str = new String(orign);
230         String regex = "("+subvalue+")";
231         if(orign.indexOf(regex)>=0)
232             str = orign.replace(regex, subvalue);
233         
234         return str;
235     }
236     private static String getFraction(int x,int y,int z)//生成一个分数
237     {
238         if(z == 0)
239             return "0";
240         double f = Math.random();//随机数
241         Fraction fr = null;//声明一个分数
242         if(f < 0.3){//如果随机数的大于0.3生成一个分数
243             //随机数c表示分子
244             int c = (int)(Math.random()*y);
245             //随机数d表示分母,注意分母不能为零
246             int d = (int)(Math.random()*(z-1))+1;
247             try {
248                 fr = new Fraction(c,d);
249                 return fr.toString();
250             } catch (Exception e) {
251                 e.printStackTrace();
252             }
253         }else{//否则生成一个整数
254             int c = (int)(Math.random()*x);
255             return ""+c;
256         }
257         return null;
258     }
259     private static String createExpress(boolean incmul,int num,int zhen,int fenzi,int fenmu,boolean withbrackets)
260     //生成一个表达式,incmul表示是否支持乘除法,num表示操作数的个数
261     {
262         if(num<2)
263             num = 2;
264         char[] operator = {‘﹢‘,‘﹣‘,‘ב,‘÷‘};//存放操作符的字符数组
265         if(!incmul)//如果不支持乘除法,将‘ב,‘÷‘替换为‘﹢‘,‘﹣‘
266         {
267             operator[2] = ‘﹢‘;
268             operator[3] = ‘﹣‘;
269         }
270         String[] strArray = new String[num];
271         char[]   opeArray = new char[num-1];
272         for(int i = 0; i < num; i++)
273         {
274             strArray[i] = getFraction(zhen,fenzi,fenmu);
275             if(i < num -1){
276                 int index = (int)(Math.random()*4);
277                 opeArray[i] = operator[index];
278             }
279         }
280         if(withbrackets)
281             insertBrackets(strArray,0,num-1);
282         String str = "";
283         for(int i = 0; i < num; i++)
284         {
285             str += strArray[i];
286             if(i < num-1)
287                 str += " "+opeArray[i]+" ";
288         }
289 
290         return str;
291     }
292     private static void insertBrackets(String[] exp,int index_1,int index_2)
293     {
294     /**
295      *2017/3/15日修改插入括号的方法,先生成操作数,然后将括号加到操作数中 
296      */
297         int y = index_2 - index_1;
298         if(y < 2)
299             return ;
300         int i = (int)(Math.random()*(y))+index_1;
301         int j = (int)(Math.random()*(y+1))+index_1;
302         if(i>j){
303             i = i^j;
304             j = i^j;
305             i = i^j;
306         }
307         int x = j - i;
308         int z = exp.length-1;
309         if(x >= 1&&x!=z&&x!=y){
310             exp[i] = "("+exp[i];
311             exp[j] = exp[j]+")";
312         }
313             
314         
315         insertBrackets(exp,index_1,i-1);
316         insertBrackets(exp,i,j);
317         insertBrackets(exp,j+1,index_2);
318     }
319     
320     private static String evaluation(String express)throws Exception//计算表达式的结果
321     {
322         //构建两个栈,分别存放分数和操作符
323         java.util.Stack<Fraction> mstack = new java.util.Stack<Fraction>();
324         java.util.Stack<Character> ostack=new java.util.Stack<Character>();
325         
326         boolean flag = false;//旗帜变量表示上一个分数是否压入了mStack栈中
327         express += "#";
328         int i = 0,len = express.length();
329         ostack.push(‘#‘);
330         String str = "";//中间字符串变量,用来读取表达式中的一个分数或者整数
331         
332         while(i < len){
333             char ch = express.charAt(i);
334             //当前字符为一个分数或者整数的一部分。
335             if((ch>=‘0‘ && ch<=‘9‘) || ch==‘/‘ || ch==‘\‘‘){
336                 str += ch;
337                 flag = true;//数没有压入栈中
338                 i++;
339             }else{//如果当前字符是空格或者操作符
340                 if(flag){//如果上一个操作数还没有压入mStack栈,怎将其压入栈中
341                     Fraction f = new Fraction(str);
342                     mstack.push(f);
343                     str = "";
344                     flag = false;//数字已经压入栈中
345                 }
346                 if(ch == ‘ ‘)//如果当前字符是空格则跳过这个字符
347                     i++;
348                 else{//以下为运算过程
349                     char op = ostack.peek();
350                     char tag = compare(op,ch);
351                     switch(tag){
352                     
353                     case ‘<‘:
354                         ostack.push(ch);i++;break;
355                     case ‘>‘:
356                         Fraction b = mstack.pop();
357                         Fraction a = mstack.pop();
358                         char oo    = ostack.pop();
359                         Fraction c = calcul(a,oo,b);
360                         if(c.lessThan(new Fraction(0)))
361                             throw new Exception("表达式"+a+oo+b+"的值为负数!");
362                         mstack.push(c);break;
363                     case ‘=‘:
364                         ostack.pop();
365                         i++;
366                         break;
367                     }
368                 }
369                 
370             }
371         }
372         Fraction r = mstack.pop();
373         return r.toString();
374     }
375     private static Fraction calcul(Fraction a, char oo, Fraction b) throws Exception//a,b按照oo所代表的操作运算
376     {
377         // TODO Auto-generated method stub
378         if(oo == ‘﹢‘)
379             return a.add(b);
380         else if(oo == ‘﹣‘)
381             return a.reduce(b);
382         else if(oo == ‘ב)
383             return a.multiply(b);
384         else if(oo == ‘÷‘)
385             return a.divide(b);
386         return null;
387     }
388     private static char compare(char s,char t)//比较s,t的优先级
389     {
390         char tag=‘<‘;                                      //临时变量,用来保存比较结果
391         switch(s){
392             case ‘﹢‘:
393                 if(t == ‘ב || t == ‘÷‘ || t == ‘(‘)
394                     tag = ‘<‘;
395                 else
396                     tag = ‘>‘;
397                 break;
398             case ‘﹣‘:
399                 if(t == ‘ב || t == ‘÷‘ || t == ‘(‘)
400                     tag = ‘<‘;
401                 else
402                     tag = ‘>‘;
403                 break;
404             case ‘ב:
405                 if(t == ‘(‘)
406                     tag = ‘<‘;
407                 else
408                     tag = ‘>‘;
409                 break;
410             case ‘÷‘:
411                 if(t == ‘(‘)
412                     tag = ‘<‘;
413                 else
414                     tag = ‘>‘;
415                 break;
416             case ‘(‘:
417                 if(t == ‘)‘)
418                     tag = ‘=‘;
419                 else if(t == ‘#‘)
420                     break;
421         }
422         return tag;
423     }
424     
425     public String[] separateAll()
426     {
427         String[] s = express.split("[\\s()]+");
428         return s;
429         
430     }
431     public Fraction[] allFigure()
432     {
433         String ss = express+" ";
434         int len = ss.length(),i=0;
435         boolean flag = false;
436         String str = "";
437         ArrayList<Fraction> list = new ArrayList<Fraction>();
438         do{
439             char ch = ss.charAt(i);
440             //当前字符为一个分数或者整数的一部分。
441             if((ch>=‘0‘ && ch<=‘9‘) || ch==‘/‘ || ch==‘\‘‘){
442                 str += ch;
443                 flag = true;//数没有压入栈中
444             }else{
445                 if(flag){
446                     try {//System.out.println(str);
447                         Fraction f = new Fraction(str);
448                         list.add(f);
449                         flag = false;
450                         str = "";
451                     } catch (Exception e) {
452                         e.printStackTrace();
453                     }
454                     
455                 }
456                 
457             }
458             i++;
459         }while(i < len);
460         int size = list.size();
461         Fraction a[] = new Fraction[size];
462         for( i = 0; i <size; i++)
463             a[i] = list.get(i);
464         return a;
465     }
466     public Equation precede()//取表达式中优先级最高的子表达式
467     {
468         try{
469             //构建两个栈,分别存放分数和操作符
470             java.util.Stack<Fraction> mstack = new java.util.Stack<Fraction>();
471             java.util.Stack<Character> ostack=new java.util.Stack<Character>();
472             String express =new String( this.express);
473             boolean flag = false;//旗帜变量表示上一个分数是否压入了mStack栈中
474             express += "#";
475             int i = 0,len = express.length();
476             ostack.push(‘#‘);
477             String str = "";//中间字符串变量,用来读取表达式中的一个分数或者整数
478             
479             while(i < len){
480                 char ch = express.charAt(i);
481                 //当前字符为一个分数或者整数的一部分。
482                 if((ch>=‘0‘ && ch<=‘9‘) || ch==‘/‘ || ch==‘\‘‘){
483                     str += ch;
484                     flag = true;//数没有压入栈中
485                     i++;
486                 }else{//如果当前字符是空格或者操作符
487                     if(flag){//如果上一个操作数还没有压入mStack栈,怎将其压入栈中
488                         Fraction f=null;
489                         try {
490                             f = new Fraction(str);
491                         } catch (Exception e) {
492                             // TODO Auto-generated catch block
493                             e.printStackTrace();
494                             f = new Fraction(1);
495                         }
496                         mstack.push(f);
497                         str = "";
498                         flag = false;//数字已经压入栈中
499                     }
500                     if(ch == ‘ ‘)//如果当前字符是空格则跳过这个字符
501                         i++;
502                     else{//以下为运算过程
503                         char op = ostack.peek();
504                         char tag = compare(op,ch);
505                         switch(tag){
506                         
507                         case ‘<‘:
508                             ostack.push(ch);i++;break;
509                         case ‘>‘:
510                             Fraction b = mstack.pop();
511                             Fraction a = mstack.pop();
512                             char oo    = ostack.pop();
513                             Fraction c = calcul(a,oo,b);
514                             String aa = a.toString();
515                             String bb = b.toString();
516                             String cc = c.toString();
517                             String newstr = aa+" "+oo+" "+bb;
518                             Equation newexp = new Equation(newstr);
519                             newexp.value =http://www.mamicode.com/ cc;
520                             return newexp;
521                         case ‘=‘:
522                             ostack.pop();
523                             i++;
524                             break;
525                         }
526                     }
527                     
528                 }
529             }
530         }catch(Exception e){e.printStackTrace();}        
531         return null;
532     }
533 }

实现分数运算的分数类:

技术分享
  1 public class Fraction {
  2 
  3     public static void main(String[] args){
  4         try {
  5             Fraction fraction = new Fraction("3/4");
  6             Fraction fraction2 = new Fraction("-2/5");
  7             Fraction fraction3 = new Fraction("0/1");
  8             System.out.println(fraction+" = "+fraction.doubleValue());
  9             System.out.println(fraction2+" = "+fraction2.doubleValue());
 10             System.out.print(fraction3+" = "+fraction3.doubleValue());
 11         } catch (Exception e) {
 12             // TODO Auto-generated catch block
 13             e.printStackTrace();
 14         }
 15     }
 16     
 17     private long numerator;//分子
 18     private long denominator;//分母
 19     
 20     public Fraction(String pattern) throws Exception{
 21         if(pattern.matches("[0-9]+‘[-]?[0-9]+/[0-9]+")){
 22             String[] s = pattern.split("[‘/]");
 23             int one = Integer.parseInt(s[0]);
 24             int tow = Integer.parseInt(s[1]);
 25             int three = Integer.parseInt(s[2]);
 26             tow += one*three;
 27             if(three==0)
 28                 throw new Exception("错误的表达式:"+pattern);
 29             numerator = tow;
 30             denominator = three;
 31             this.yuefen();
 32         }else if(pattern.matches("[-]?[0-9]+/[0-9]+")){
 33             String[] s = pattern.split("/");
 34             int one = Integer.parseInt(s[0]);
 35             int tow = Integer.parseInt(s[1]);
 36             if(tow==0)
 37                 throw new Exception("错误的表达式:"+pattern);
 38             numerator = one;
 39             denominator=tow;
 40             this.yuefen();
 41         }else if(pattern.matches("[-]?[0-9]+")){
 42             int one = Integer.parseInt(pattern);
 43             numerator = one;
 44             denominator=1;
 45         }else{
 46             throw new Exception("不正确的表达式"+pattern);
 47         }
 48     }
 49     public Fraction(long x1,long x2) throws Exception {
 50         // TODO Auto-generated constructor stub
 51         if(x2==0)
 52             throw new Exception("denominator can‘t be 0!");
 53         if(x1<0&&x2<0)
 54         {
 55             x1 *= -1;x2 *= -1;
 56         }else if(x2 <0&&x1>0){
 57             x1 *= -1;x2 *= -1;
 58         }
 59         this.numerator = x1;
 60         this.denominator=x2;
 61         this.yuefen();
 62     }
 63     public Fraction(long x){
 64         this.numerator=x;
 65         this.denominator=1;
 66     }
 67     public Fraction() {
 68         this(1);
 69     }
 70     public Fraction(Fraction frac){
 71         this.numerator  = frac.numerator;
 72         this.denominator = frac.denominator;
 73     }
 74 
 75     public long getNumerator(){return numerator;}
 76     public long getDenominator(){return denominator;}
 77     public void setNumerator(long num){numerator=num;}
 78     public void setDenominator(long deno){denominator=deno;}
 79     
 80     
 81     private static long maxComDiv(long x1,long x2){//求两个数的最大公约数
 82         long sum = 1;
 83         long temp =x1<x2? x1:x2;
 84         for(int i = 2; i <= temp;i++)
 85         {
 86             if(x1%i==0&&x2%i==0)
 87                 sum = i;
 88         }
 89         return sum;
 90     }
 91     private static long lcm(long x1,long x2){//求两个数的最小公倍数
 92         return x1*x2/maxComDiv(x1, x2);
 93     }
 94     private void yuefen(){//约分
 95         //求分子和分母的最大公约数
 96         long x = Fraction.maxComDiv(this.numerator, this.denominator);
 97         if(x != 1){
 98             //如果分子分母的最大公约数不是1,分子分母同时除以这个数
 99             this.numerator/=x;this.denominator/=x;
100         }
101     }
102     private static void tongfen(Fraction x,Fraction y){//通分
103         
104         if(x.denominator==y.denominator)
105             return ;
106         //求两个分母的最小公倍数m
107         long m = lcm(x.denominator,y.denominator);
108         x.numerator *= (m/x.denominator);
109         y.numerator *= (m/y.denominator);
110         x.denominator = m;
111         y.denominator = m;
112     }
113 
114     public Fraction reciprocal() throws Exception{//求倒数
115         if(this.numerator==0)
116             throw new Exception("0没有倒数!");
117         return new Fraction(this.denominator,this.numerator);
118     }
119     
120     public Fraction multiply(Fraction another)//当前对象同另外一个分数相加返回一个新的分数
121     {
122         Fraction frac = null;
123         try{//对象在定义的时候已经有过分母为0的异常处理了,
124             //此处本来可以不用异常处理的,因为两个合法的分数相乘不可能出现分母为0
125             frac = new Fraction(numerator*another.numerator,denominator*another.denominator);
126         }catch(Exception e){}
127         frac.yuefen();
128         return frac;
129     }
130 
131     public Fraction divide(Fraction another) throws Exception//当前分数除以一分数,返回结果分数
132     {
133         //处理除数为0的异常情况
134         if(another.numerator==0)
135             throw new Exception("除数不能为0!");
136         //求another的倒数
137         Fraction temp = another.reciprocal();
138         //返回当前分数和another倒数的乘积
139         return multiply(temp);
140         
141     }
142     
143     public Fraction add(Fraction another)//分数相加
144     {
145         //如果两个分数的分母相同,直接分子相加
146         if(this.denominator==another.denominator)
147             try {
148                 return new Fraction(this.numerator+another.numerator,this.denominator);
149             } catch (Exception e) {
150             }
151         //将当前分数this对象和another分别赋值给新的对象,因为分数加法需要通分
152         //新的对象通分后原来的对象不会改变。
153         Fraction x = new Fraction(this),y = new Fraction(another);
154         //新对象x,y通分得到两个分母相同的分数
155         tongfen(x,y);
156         //分母相同的分数分子相加
157         x.numerator+=y.numerator;
158         x.yuefen();
159         return x;
160     }
161 
162     public Fraction reduce(Fraction another)//分数相减
163     {
164         Fraction x =new Fraction(this);
165         //如果分母相同
166         if(x.denominator==another.denominator){
167             x.numerator-=another.numerator;
168             x.yuefen();
169             return x;
170         }
171         Fraction y = new Fraction(another);
172         tongfen(x,y);
173         x.numerator-=y.numerator;
174         x.yuefen();
175         return x;
176     }
177     
178     public Fraction multiply(int x)//分数和一个整数相乘
179     {
180         Fraction y = new Fraction(x);
181         return this.multiply(y);
182     }
183     
184     public Fraction divide(int x) throws Exception//除以另一个分数
185     {
186         Fraction y = new Fraction(x);
187         return this.divide(y);
188     }
189     
190     public Fraction add(int x)//分数和一个int类型的数相加
191     {
192         //将int类型数据转化为分数
193         Fraction y=new Fraction(x);
194         //调用分数加分数的方法得到结果
195         return this.add(y);
196     }
197     
198     public Fraction reduce(int x)//分数减去一个整数
199     {
200         Fraction y = new Fraction(x);
201         return this.reduce(y);
202     }
203     
204     public String toString()//将分数化为字符串用于输出
205     {
206         if(numerator > denominator&&denominator!=1){
207             long t1 = numerator / denominator;
208             long t2 = numerator - t1*denominator;
209             return ""+t1+"‘"+t2+"/"+denominator;
210         }
211         if(this.numerator==0||this.denominator==1)
212             //当分子为0或者分母为1的时候直接输出分子
213             return ""+this.numerator;
214         else
215             return this.numerator+"/"+this.denominator;
216     }
217 
218     public double doubleValue()//将分数化为浮点数
219     {
220         return (double)this.numerator/(double)this.denominator;
221     }
222     
223     public int intValue(){
224         return (int)(this.numerator/this.denominator);
225     }
226     
227     public boolean lessThan(Fraction target)//比较当前分数和target的大小
228     {
229         Fraction x = new Fraction(this),y = new Fraction(target);
230         tongfen(x,y);
231         if(x.numerator < y.numerator)
232             return true;
233         else
234             return false;
235     }
236     public boolean equals(Fraction target)//判断相等
237     {
238         Fraction x = new Fraction(this),y = new Fraction(target);
239         if(x.numerator==y.numerator)
240             return true;
241         else
242             return false;
243     }
244     public boolean greaterThan(Fraction target)
245     {
246         Fraction x = new Fraction(this),y = new Fraction(target);
247         if(x.numerator>y.numerator)
248             return true;
249         else
250             return false;
251     }
252 }
View Code

 

 

运行结果截图

技术分享

 

技术分享

 

技术分享

编程总结分析

 

 

 

PSP开发记录表

日期

开始时间

结束时间

中断时间

净时间

活动

2017/3/13

14:00

15:50

10minute

100minute

上课

2017/3/13

16:10

17:50

10minute

100minute

设计

2017/3/13

18:46

22:30

17minute

223minute

编程

2017/3/14

12:26

15:50

 

270minute

编程

2017/3/14

16:10

17:40

 

90minute

编程

2017/3/14

21:03

22:50

 

107minute

复审

2017/3/15

12:35

14:50

 

135minute

复审

2017/3/16

18:30

17:50

 

80minute

整理写博客

四则运算三