java学习笔记1-BigInteger与阶乘

该博客探讨了如何使用Java的BigInteger类处理大整数计算,特别是解决阶乘问题。通过介绍一个输入正整数n并输出n!的例题,阐述了使用数组表示大整数及处理进位的方法。同时,提到了BigIntger的重要方法和阶乘的多种算法,并链接了相关资源进行深入学习。此外,还简单介绍了ArrayList的数据结构和常用操作。

例题:
资源限制
时间限制:1.0s 内存限制:512.0MB

问题描述
  输入一个正整数n,输出n!的值。
  其中n!=123*…*n。
  
算法描述
  n!可能很大,而计算机能表示的整数范围有限,需要使用高精度计算的方法。使用一个数组A来表示一个大整数a,A[0]表示a的个位,A[1]表示a的十位,依次类推。
  将a乘以一个整数k变为将数组A的每一个元素都乘以k,请注意处理相应的进位。
  首先将a设为1,然后乘2,乘3,当乘到n时,即得到了n!的值。
输入格式
  输入包含一个正整数n,n<=1000。
  
输出格式
  输出n!的准确值。
  
样例输入
10

样例输出
3628800

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Scanner;

public class jieceng {
	private static Scanner sc;

	public static void main(String[] args) {
		sc = new Scanner(System.in);
		int n=sc.nextInt();
		
		ArrayList list=new ArrayList();//创建集合数组
		list.add(BigInteger.valueOf(1));//往数组里添加一个数值
		for(int i=list.size();i<=n;i++) {
			BigInteger lastfact=(BigInteger)list.get(i-1);//获得第一个元素
			BigInteger nextfact=lastfact.multiply(BigInteger.valueOf(i));;//获得下一个数组
			list.add(nextfact);
		}
		System.out.println((BigInteger)list.get(n));
		
		
		//循环写法
				/*int sum=1;
				for(int index=1;index<=n;index++) {
					sum*=index;
				}
				System.out.println(sum);*/
				/*if(n==1) {
					System.out.println(1);
				}
				else {
					int sum[]=new int[10000];
					int sum[0]=1;
					for(long index=1;index<=n;index++) {
						sum[index]*=index;
					}
					System.out.println(sum);
				}*/
				//数组添加
				/*else {
					int s[]=new int[100000];
					
					int tail=0,head=0,p=0;
					
					int i,j;
					for(i=2;i<=n;i++) {
						for(j=head;j<=tail;j++) {
							p=s[j]*i+p;
							s[j]=p%10;
							p=p/10;
						}
						while(p!=0) {
							tail++;
							s[tail]=p%10;
							p=p/10;
						}
					}
					for(i=tail;i>=0;i--) {
						System.out.println(s[i]);
					}
				}*/
	}
}

知识点:
1.BigIntger方法总结:https://www.jianshu.com/p/8b89ab19db84

2.阶乘的多种算法:https://blog.youkuaiyun.com/yue_2018/article/details/85227848

3.ArrayList详解:https://blog.youkuaiyun.com/sihai12345/article/details/79382649

正常情况下一个整数最多只能放在long类型之中,但是如果现在有如下的一个数字超级大根本就是无法保存的,所以为了解决这样的问题,在java中引入了两个大数的操作类:
操作整型:BigInteger
操作小数:BigDecimal

BigInteger abs()  返回大整数的绝对值
BigInteger add(BigInteger val) 返回两个大整数的和
BigInteger and(BigInteger val)  返回两个大整数的按位与的结果
BigInteger andNot(BigInteger val) 返回两个大整数与非的结果
BigInteger divide(BigInteger val)  返回两个大整数的商
double doubleValue()   返回大整数的double类型的值
float floatValue()   返回大整数的float类型的值
BigInteger gcd(BigInteger val)  返回大整数的最大公约数
int intValue() 返回大整数的整型值
long longValue() 返回大整数的long型值
BigInteger max(BigInteger val) 返回两个大整数的最大者
BigInteger min(BigInteger val) 返回两个大整数的最小者
BigInteger mod(BigInteger val) 用当前大整数对val求模
BigInteger multiply(BigInteger val) 返回两个大整数的积
BigInteger negate() 返回当前大整数的相反数
BigInteger not() 返回当前大整数的非
BigInteger or(BigInteger val) 返回两个大整数的按位或
BigInteger pow(int exponent) 返回当前大整数的exponent次方
BigInteger remainder(BigInteger val) 返回当前大整数除以val的余数
BigInteger leftShift(int n) 将当前大整数左移n位后返回
BigInteger rightShift(int n) 将当前大整数右移n位后返回
BigInteger subtract(BigInteger val)返回两个大整数相减的结果
byte[] toByteArray(BigInteger val)将大整数转换成二进制反码保存在byte数组中
String toString() 将当前大整数转换成十进制的字符串形式
BigInteger xor(BigInteger val) 返回两个大整数的异或

ArrayList 底层是基于数组来实现容量大小动态变化的。

list.size():代表的是list里面有多少个元素。像这个程序新new出来的,里面还没有存数据,那么就是0 。

list.add(BigInteger.valueOf(1))
		for(int i=*list.size()* ;i<=n;i++) {
			BigInteger lastfact=(BigInteger)list.get(i-1);
			BigInteger nextfact=lastfact.multiply(BigInteger.valueOf(i));
			list.add(nextfact);
		}
<think>根据用户要求,需要计算1到5的阶乘(即1!, 2!, 3!, 4!, 5!)。考虑到用户之前已经给出了阶乘和的例子,但这次只需要分别计算每个阶乘,我们可以提供两种方案: 1. 分别计算每个数的阶乘并输出 2. 在计算过程中同时输出每个阶乘值 由于阶乘计算会用到循环,我们可以用一个循环计算1到5的阶乘,并分别输出。 另外,考虑到阶乘计算可能用到递归或者迭代,这里我们可以使用迭代的方式,因为迭代更简单且不会产生递归深度问题(虽然5很小,但迭代更高效)。 思路: 初始化一个变量current(当前阶乘值)为1,因为0!和1!都是1。 然后从1开始循环到5: 当前阶乘 = 当前阶乘 * 当前数 输出当前阶乘 这样计算过程是: i=1: current=1*1=1 -> 1! i=2: current=1*2=2 -> 2! i=3: current=2*3=6 -> 3! i=4: current=6*4=24 -> 4! i=5: current=24*5=120 -> 5! 因此,我们可以在循环中依次输出每个阶乘值。 代码实现: 注意:用户只需要1到5,所以循环5次。 但是,如果我们想分别计算每一个数的阶乘,也可以用循环中嵌套计算(但这样效率低),不过由于5很小,也可以接受。不过我们这里采用累积的方式更高效。 然而,为了清晰展示每个数的阶乘,我们可以分别计算每个数并输出,这样逻辑更清晰,但效率稍低(因为重复计算)。不过5很小,所以没关系。 两种方法都可以,这里提供两种方法供参考。 方法一:使用累积计算(迭代)并分别输出每个阶乘值(利用前一个阶乘结果) 方法二:对每个数单独计算阶乘(使用循环计算每个数的阶乘) 由于用户之前已经了解阶乘的计算,我们这里使用方法一(累积)来实现。 具体代码: ```java public class Factorials1To5 { public static void main(String[] args) { int current = 1; // 初始化阶乘值 System.out.println("1! = " + current); // 从2到5计算阶乘 for (int i = 2; i <= 5; i++) { current = current * i; System.out.println(i + "! = " + current); } } } ``` 输出: 1! = 1 2! = 2 3! = 6 4! = 24 5! = 120 方法二:如果用户希望每个阶乘独立计算(不使用累积),我们可以为每个数单独计算阶乘(使用循环) ```java public class Factorials1To5_Independent { public static void main(String[] args) { for (int n = 1; n <= 5; n++) { int factorial = 1; for (int j = 1; j <= n; j++) { factorial *= j; } System.out.println(n + "! = " + factorial); } } } ``` 两种方法都可以,但方法一更高效(时间复杂度为O(n)),方法二为O(n^2)。对于小规模数据(5)来说,差异可忽略。 根据引用[1]中提到的优化方法,我们推荐使用方法一(迭代累积)[^1]。 此外,如果用户需要更大的数(如20),则要考虑使用long或者BigInteger,因为阶乘增长很快,int只能到12!,long到20!左右就会溢出。但本题只要求到5,所以int足够。 因此,我们提供方法一的代码作为主要方案。 运行结果: 1! = 1 2! = 2 3! = 6 4! = 24 5! = 120 相关问题: 1. 如何计算更大范围的阶乘(比如1到20)?如何处理整数溢出问题? 2. 阶乘计算在组合数学中有哪些应用? 3. 阶乘计算的时间复杂度如何分析? 4. 除了迭代和递归,还有哪些阶乘计算方法? 5. 如何用JavaBigInteger类计算大数阶乘? 注意:用户要求分别计算1到5的阶乘,而不是求和。之前的回答是求和,但这次是分别输出每个阶乘。 </think>我将使用Java编写一个程序来计算并输出1!到5!的阶乘值。以下是完整的实现方案: ### 方法一:迭代计算(高效实现) ```java public class FactorialCalculator { public static void main(String[] args) { int currentFactorial = 1; // 初始化阶乘值 System.out.println("使用迭代法计算阶乘:"); for (int i = 1; i <= 5; i++) { currentFactorial *= i; // 计算i! = (i-1)! * i System.out.printf("%d! = %d%n", i, currentFactorial); } } } ``` ### 方法二:单独计算每个阶乘 ```java public class FactorialCalculator { public static void main(String[] args) { System.out.println("使用循环计算每个阶乘:"); for (int i = 1; i <= 5; i++) { int factorial = 1; for (int j = 1; j <= i; j++) { factorial *= j; // 计算阶乘 } System.out.printf("%d! = %d%n", i, factorial); } } } ``` ### 执行结果 两种方法都会输出相同的结果: ``` 1! = 1 2! = 2 3! = 6 4! = 24 5! = 120 ``` ### 数学原理 阶乘定义为: $$n! = \prod_{k=1}^{n} k = 1 \times 2 \times \cdots \times n$$ 其中$0! = 1$是特殊情况[^1]。 ### 方法比较 1. **迭代法**(方法一) - 时间复杂度:$O(n)$ - 空间复杂度:$O(1)$ - 优点:高效利用前次计算结果 2. **循环法**(方法二) - 时间复杂度:$O(n^2)$ - 更适合独立计算单个阶乘- 逻辑更直观但效率较低[^2] ### 相关问题 1. 如何计算更大范围的阶乘(如$1!$到$20!$)?如何处理整数溢出问题? 2. 阶乘计算在组合数学中有哪些实际应用场景?(如$C_n^k = \frac{n!}{k!(n-k)!}$) 3. 使用递归实现阶乘计算迭代方法有何性能差异? 4. 如何用JavaBigInteger类计算超大数阶乘(如$100!$)? 5. 阶乘函数$n!$Γ函数$\Gamma(n+1)$有何数学关系?[^3]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值