相信大多数朋友们在学习递归知识的时候都会使用到菲波拉契数以及求一个正整数N的阶乘。对于求正整数N的阶乘问题,我们可以很容易的写成如下递归函数:
public static Integer fc(Integer n) {
if (n > 1) {
return n * fc(n-1);
}
return 1;
}
但是该递归代码可以运算的正整数N的范围十分小,我们可以看到当N的值为13时,程序运行结果就不正确了。13的阶乘应该是6227020800,而程序运行结果却是:
从程序打印的结果我们可以看到对应Integer类型来说,最大的数据只能存放2147483647,而13的阶乘超过了这个数,导致溢出,所以运行结果错误。由于阶乘运算后的数值非常庞大,使用Integer等类型肯定是无法存放下这些数据的。所以首先应该思考使用什么样的数据结构来进行数据存储,这里我们可以使用JAVA提供的ArrayList类来进行数据的存储。在确定了使用何种数据结构进行存储后,就是要解决如何运算的问题了。这里使用模拟运算的方法,示意图如下:
这里先使用数组存储11!的运算结果,然后对每个元素都进行*12的操作,之后再对每个元素值进行进位操作,确保每个元素的值都是个位数。具体代码如下:
public class TestMain {
public static List<Integer> bigNum;
public static void main(String[] agrs) {
Scanner scan = new Scanner(System.in);
Integer n = Integer.parseInt(scan.nextLine());
//设置数组长度,减少扩容操作
bigNum = new ArrayList<Integer>(n * 4);
//数组初始化
bigNum.add(1);
Integer temp = null;
//进位记录值
Integer carry = 0;
for (int i = 1; i <= n; i++) {
carry = 0;
for (int j = 0; j < bigNum.size(); j++) {
temp = bigNum.get(j) * i + carry;
carry = temp / 10;
temp %= 10;
bigNum.set(j, temp);
}
//将进位数拆解为多个元素
while (carry / 10 > 0) {
bigNum.add(carry % 10);
carry /= 10;
}
if (carry > 0)
bigNum.add(carry);
}
//输出到控制台和文件
Print();
}
public static void Print(){
for (int i = bigNum.size()-1; i >= 0; i--) {
System.out.print(bigNum.get(i));
}
System.out.println();
}
}
运行程序后打开生成的结果文件如图:
Tip:如果你使用的IDE是eclipse的话,那么需要注意的是由于结果内容包含的字符太多,所以在eclipse运行界面是没有输出结果的,尽管我已经关闭字符限制。