A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

  1. import java.util.Arrays;

  2. public class BigFactorial {
  3.         private static final int MAXDIGITS = 10000; // 能容纳的阶乘结果的最大位数
  4.          private static int digits; // n!的位数
  5.          private static int[] result = new int[MAXDIGITS]; // 阶乘结果的逆序

  6.          public static void main(String[] args) {
  7.                  int n = 1000;
  8.                  calFact(n);
  9.                  printResult(n);
  10.                  System.out.println("共包含 " + countAllZeroes() + " 个0,末尾有" + countTrailingZeroes() + "个0");
  11.          }
  12.        
  13.          /**
  14.          * 计算n! = 1 * 2 *...* n,将n!的各位数逆序存入result数组中,并返回n!的位数。
  15.           * 计算原理:
  16.          *          2! = 2 * 1!; 3! = 3 * 2!; k! = k * (k-1)! 以此类推
  17.           *   k!的各位数以逆序方式存放在数组中,逆序存放的原因是方便处理乘积各位向高位的进位。
  18.           *           例如7!=5040,在数组中存储为0405。0405与8的乘积为
  19.           *                   个位:0*8                 = 0
  20.          *                   十位:(4*8)%10 + 个位进位0 = 2
  21.           *                   百位:0*8 + 十位进位3      = 3
  22.          *                   千位:(5*8)%10 + 百位进位0 = 0
  23.           *          万位:千位进位4            = 4
  24.          *          逆序后即为8!=40320
  25.           * @param n 大于等于0的整数
  26.           * @return n!结果的位数
  27.          */
  28.         public static void calFact(int n) {
  29.                 init(); // 初始化result和digits

  30.                 int product = 0; // k!的第m位数与k+1的乘积,加上第m-1位数上的进位(k=1,2...n-1)
  31.                 int carry = 0; // 进位
  32.                 for (int i = 2; i <= n; i++) {
  33.                         for (int j = 0; j < digits; j++) {
  34.                                 product = result[j] * i + carry;
  35.                                 carry = product / 10;
  36.                                 result[j] = product % 10;
  37.                                 if (j == digits - 1 && carry != 0) // 当前结果的最高位需要进位
  38.                                         digits++;
  39.                         }
  40.                 }
  41.         }
  42.        
  43.         private static void init() {
  44.                  Arrays.fill(result, 1, MAXDIGITS - 1, 0);
  45.                  result[0] = 1;
  46.                 digits = 1;
  47.         }
  48.        
  49.         /**
  50.          * 逆序打印阶乘结果
  51.          * @param n
  52.          */
  53.         public static void printResult(int n) {
  54.                 System.out.print(n + "! = ");
  55.                 for (int i = digits - 1; i >= 0; i--) {
  56.                         System.out.print(result[i]);
  57.                 }
  58.                 System.out.println();
  59.         }
  60.        
  61.         /**
  62.          * 统计阶乘结果中0的个数
  63.          * @return 阶乘结果中0的个数
  64.          */
  65.         public static int countAllZeroes() {
  66.                 int zeroCount = 0;
  67.                 for (int i = digits - 1; i >= 0; i--) {
  68.                         if (result[i] == 0)
  69.                                 zeroCount++;
  70.                 }
  71.                 return zeroCount;
  72.         }
  73.        
  74.         /**
  75.          * 统计阶乘结果末尾0的个数
  76.          * @return 阶乘结果末尾0的个数
  77.          */
  78.         public static int countTrailingZeroes() {
  79.                 int zeroCount = 0;
  80.                 for (int i = 0; i < digits; i++)
  81.                         if (result[i] == 0)
  82.                                 zeroCount++;
  83.                         else
  84.                                 break;
  85.                 return zeroCount;
  86.         }
  87. }
复制代码


评分

参与人数 1技术分 +1 收起 理由
格子、 + 1 要水吹水圣地水去!!!

查看全部评分

13 个回复

倒序浏览
这两天正被这个问题困扰的焦头烂额,楼主真乃及时雨啊,学习一下,今晚安能睡个踏实觉了,多谢。:handshake
回复 使用道具 举报
我简直要成为你的忠实观众了,太牛了。顺便问一下,发表主题的时候像你那样显示规矩的代码段是怎么弄得
回复 使用道具 举报
为爱编程 发表于 2014-8-1 16:41
我简直要成为你的忠实观众了,太牛了。顺便问一下,发表主题的时候像你那样显示规矩的代码段是怎么弄得 ...

谢谢:handshake。代码段功能在此

回复 使用道具 举报
貌似看都看不懂
回复 使用道具 举报

先回忆一下小学乘法是怎么分步计算的
回复 使用道具 举报
烟海 中级黑马 2014-8-12 22:54:54
7#
fantacyleo 发表于 2014-8-12 22:39
先回忆一下小学乘法是怎么分步计算的

{:3_56:} 我也没怎么看懂。。。。

看着就觉得好复杂的样子。。。
回复 使用道具 举报
烟海 发表于 2014-8-12 22:54
我也没怎么看懂。。。。

看着就觉得好复杂的样子。。。

核心方法就只有calFact,注释里有一个例子,纯属小学乘法
回复 使用道具 举报
烟海 中级黑马 2014-8-12 23:38:10
9#
fantacyleo 发表于 2014-8-12 23:05
核心方法就只有calFact,注释里有一个例子,纯属小学乘法

好吧。。明天再逼着自己。。。重新看一遍。。。现在不想看代码。。。
回复 使用道具 举报
楼主不错  认真的看了一遍  看了两边,最后自己敲了一遍。理解  think you 收获
回复 使用道具 举报
其实如果只想知道 n! 的末尾有几个0的话,计算 n/5 + n/(5^2) + n/(5^3)……的结果就好了。我一个朋友去面试数学老师,被问到这题,于是她充满恶意地来问我。
回复 使用道具 举报
代码看多了,看到这么绕,都晕了!!
回复 使用道具 举报
楼主厉害····学习了·
回复 使用道具 举报
Rdxer 中级黑马 2015-5-23 22:35:02
14#
不要太diao了
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马