黑马程序员技术交流社区

标题: 高手请进 [打印本页]

作者: 权跃杰    时间: 2012-7-31 16:20
标题: 高手请进
老师或高手请进!!
对比下列2段代码:
代码1
class A{
  public static void main(String args[]){
     System.out.println("1!+2!+3!+4!+...+18!+19!+20!="+sum()) ;
  }
  public static long sum(){   //求出所有数字阶乘的和
     long sum = 0l ;
     for(int i = 1 ; i <= 20 ; i++){
        sum+=num(i) ;
     }
     return sum ;
  }
  public static double num(int x) {  //求出单个数字的阶乘是多少
    if(x==0||x==1){
       return 1 ;
    }else{
       return x * num(x-1) ;
    }
  }
}



代码2
public class Practice11{
public static void main(String args[]){
  long sum = 0L;
  for (int x = 1; x<=20; x++){
   sum += Factorial(x);
  }
  System.out.println("1!+2!+3!+...+20!结果是:" + sum);
}
public static long Factorial(int k){
  if (k == 0||k == 1){
   return 1;
  }else{
   return k * Factorial(k-1);
  }
}
}


为什么产生的结果不一样!
第一个结果是:1!+2!+3!+4!+...+18!+19!+20!=2561327494111820288
第二个结果是:1!+2!+3!+...+20!          结果是:2561327494111820313

不是我这人较劲啊,为什么结果不同?请老师或者高手给予解答?

作者: 涂金哲    时间: 2012-7-31 16:27
public class Test2{
public static void main(String args[]){
  long sum = 0L;
  for (int x = 1; x<20; x++){//这里改为x<20就OK了,循环次数问题哈
   sum += Factorial(x);
  }
  System.out.println("1!+2!+3!+...+20!结果是:" + sum);
}
public static long Factorial(int k){
  if (k == 0||k == 1){
   return 1;
  }else{
   return k * Factorial(k-1);
  }
}
}
作者: 涂金哲    时间: 2012-7-31 16:29
sorry 错了 我运行错了哈 没看清哈
作者: 金龙    时间: 2012-7-31 16:38
问题出在代码1上,以下是你的代码

class A{
  public static void main(String args[]){
     System.out.println("1!+2!+3!+4!+...+18!+19!+20!="+sum()) ;
  }
  public static long sum(){   //求出所有数字阶乘的和
     long sum = 0l ;
     for(int i = 1 ; i <= 20 ; i++){
        sum+=num(i) ;
     }
     return sum ;
  }
  public static double num(int x) {  //这里的返回值类型是double,而你运算的结果应该是long,在这里,丢失精度了,你把double改回long就可以啦,是精度损失的问题
    if(x==0||x==1){
       return 1 ;
    }else{
       return x * num(x-1) ;
    }
  }
}
作者: 涂金哲    时间: 2012-7-31 16:52
传入19的时候两个结果一样  传入21的时候会出现负数  所以可以说明了计算的结果超过了long类型的存储范围了
作者: 创出一片辉煌    时间: 2012-7-31 16:53
第2段代码是对的,第1段代码中问题应该在 public static double num(int x) 中,整个运算都是整形运算,
为什么要加入DOUBLE浮点运算呢?  你把DOUBLE 该成LONG就没有问题了。
另外,运算方面有点问题,虽然不影响最后的结果,
但我还是想说,你仔细观察第一段代码中的X  和  第二段代码中的K  其实他们的值永远也到不了“0”,
你看看对不对,比如现在执行到return k * Factorial(k-1);语句,假设此时K=2,  执行K-1后新的K=1,
调用Factorial(K)函数,就进入IF判断环节,当判断为1后,返回值,IF语句就完全退出了,不再循环了。
也就不存在再次调用Factorial(K)函数,所以IF语句中对K=0的判断是多余的,去掉后运行结果没有改变。
最后,很感谢让我学到了一种新的循环方式!祝进步
作者: 李知伦    时间: 2012-7-31 17:07
刚想回,发现没权限,弄好了回来发现被LS回答了。。。。
第一段代码的num()函数返回值类型不对,应为long
补充一点说,5!以上都是个位数为0的数,所以你很容易只算出1-4的阶乘的个位数,就能很容易判断出是,第二段代码的返回值相对准确。
作者: 权跃杰    时间: 2012-8-1 19:22
问题已解决




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2