大数问题:求n的阶乘

题目:求100!

这看起来是一个很简答的问题,递归解之毫无压力

int func(int n){
    if(n <= 1) return 1;
    else return n*func(n-1);
}

但你会发现,题目真的有这么简单吗,考虑整形数据越界没有?

这实际上是一个大数问题!

大数怎么表示呢,很直接的,我们会想到用字符串来表示,但表示的过程中还得做阶乘运算,是不是想象的那么复杂呢?

其实,用基本的乘法运算思想(从个位到高位逐位相乘,进位)来考虑,将临时结果的每位与阶乘元素相乘,向高位进位,问题并不是那么复杂。

代码中注释很详细,不多说,直接贴在下面了。

	public static void main(String[] args) throws IOException {
		int digit = 1; 		// 位数
		int temp; 			// 阶乘的任一元素与临时结果的某位的乘积结果
		int i, j, carry; 					// 进位
		boolean isnavigate = false;			// 输入的数是正数还是负数
		int[] a = new int[3000]; 			// 确保保存最终运算结果的数组足够大
		System.out.println("请输入一个数字,求它的阶乘");
		String nStr = ClassicalIOCode.getSystemInput();
		int n = 1;
		try {
			n = Integer.parseInt(nStr);
		}catch(NumberFormatException nfe) {
			System.out.println("请输入合法的正整数!");
			return;
		}
		if(n < 0) {
			n = -n;
			isnavigate = true;
		}
		a[0] = 1; 							// 将结果先初始化为1
		for (i = 2; i <= n; i++) { 			// 开始阶乘,阶乘元素从2开始依次"登场"
			// 按最基本的乘法运算思想(从个位到高位逐位相乘,进位)来考虑,将临时结果的每位与阶乘元素相乘
			for (j = 1, carry = 0; j <= digit; j++) { // carry:进位
				temp = a[j - 1] * i + carry; // 相应阶乘中的一项与当前所得临时结果的某位//相乘(加上进位)
				a[j - 1] = temp % 10; 		// 更新临时结果的位上信息
				carry = temp / 10; 			// 看是否有进位
			}
			while (carry != 0) { 			// 如果有进位
				a[++digit - 1] = carry % 10; // 新加一位,添加信息。位数增1
				carry = carry / 10; 		// 看还能不能进位
			}
		}
		if(isnavigate) {
			if(n % 2 == 1) {
				System.out.print((-n) + "的阶乘:"+ (-n) +"! = -"); // 显示结果
			}else {
				System.out.print((-n) + "的阶乘:"+ (-n) +"! = "); // 显示结果
			}
		}else {
			System.out.print(n + "的阶乘:"+ n +"! = "); // 显示结果
		}
		for (j = digit; j >= 1; j--) {
			System.out.print(a[j - 1]);
		}
		System.out.println();
	}
点赞