- import java.util.Arrays;
- public class BigFactorial {
- private static final int MAXDIGITS = 10000; // 能容纳的阶乘结果的最大位数
- private static int digits; // n!的位数
- private static int[] result = new int[MAXDIGITS]; // 阶乘结果的逆序
- public static void main(String[] args) {
- int n = 1000;
- calFact(n);
- printResult(n);
- System.out.println("共包含 " + countAllZeroes() + " 个0,末尾有" + countTrailingZeroes() + "个0");
- }
-
- /**
- * 计算n! = 1 * 2 *...* n,将n!的各位数逆序存入result数组中,并返回n!的位数。
- * 计算原理:
- * 2! = 2 * 1!; 3! = 3 * 2!; k! = k * (k-1)! 以此类推
- * k!的各位数以逆序方式存放在数组中,逆序存放的原因是方便处理乘积各位向高位的进位。
- * 例如7!=5040,在数组中存储为0405。0405与8的乘积为
- * 个位:0*8 = 0
- * 十位:(4*8)%10 + 个位进位0 = 2
- * 百位:0*8 + 十位进位3 = 3
- * 千位:(5*8)%10 + 百位进位0 = 0
- * 万位:千位进位4 = 4
- * 逆序后即为8!=40320
- * @param n 大于等于0的整数
- * @return n!结果的位数
- */
- public static void calFact(int n) {
- init(); // 初始化result和digits
- int product = 0; // k!的第m位数与k+1的乘积,加上第m-1位数上的进位(k=1,2...n-1)
- int carry = 0; // 进位
- for (int i = 2; i <= n; i++) {
- for (int j = 0; j < digits; j++) {
- product = result[j] * i + carry;
- carry = product / 10;
- result[j] = product % 10;
- if (j == digits - 1 && carry != 0) // 当前结果的最高位需要进位
- digits++;
- }
- }
- }
-
- private static void init() {
- Arrays.fill(result, 1, MAXDIGITS - 1, 0);
- result[0] = 1;
- digits = 1;
- }
-
- /**
- * 逆序打印阶乘结果
- * @param n
- */
- public static void printResult(int n) {
- System.out.print(n + "! = ");
- for (int i = digits - 1; i >= 0; i--) {
- System.out.print(result[i]);
- }
- System.out.println();
- }
-
- /**
- * 统计阶乘结果中0的个数
- * @return 阶乘结果中0的个数
- */
- public static int countAllZeroes() {
- int zeroCount = 0;
- for (int i = digits - 1; i >= 0; i--) {
- if (result[i] == 0)
- zeroCount++;
- }
- return zeroCount;
- }
-
- /**
- * 统计阶乘结果末尾0的个数
- * @return 阶乘结果末尾0的个数
- */
- public static int countTrailingZeroes() {
- int zeroCount = 0;
- for (int i = 0; i < digits; i++)
- if (result[i] == 0)
- zeroCount++;
- else
- break;
- return zeroCount;
- }
- }
复制代码
|