偶然机会发现了在Java中有两个特别的类BigDecimal和BigInteger,他们分别可以存储非常大的浮点型变量和整型变量,API文档的说明如下:
用这个类可以表示任意精度的整数,只要你的电脑内存够大。继续往下翻,可以看到这个类提供了很多可调用的方法,结合这道题目,我觉得这么几个方法我们可能会用上:
*首先是一个构造方法,可以通过一个字符串构造一个BigInteger变量
BigInteger
public BigInteger(String val)将 BigInteger 的十进制字符串表示形式转换为 BigInteger。该字符串表示形式包括一个可选的减号,后跟一个或多个十进制数字序列。字符到数字的映射由 Character.digit 提供。该字符串不能包含任何其他字符(例如,空格)。
参数:
val - BigInteger 的十进制字符串表示形式。
抛出:
NumberFormatException - val 不是 BigInteger 的有效表示形式。
*然后是加法、乘法和除法运算方法
**add**
public BigInteger add(BigInteger val)返回其值为 (this + val) 的BigInteger。
参数:
val - 将添加到此 BigInteger 中的值。
返回:
this + val
**multiply**
public BigInteger multiply(BigInteger val)返回其值为 (this * val) 的 BigInteger。
参数:
val - 要乘以此 BigInteger 的值。
返回:
this * val
**divide**
public BigInteger divide(BigInteger val)返回其值为 (this / val) 的 BigInteger。
参数:
val - 此 BigInteger 要除以的值。
返回:
this / val
抛出:
ArithmeticException - val==0
那么如此一来,我们就可以轻易的计算出这个表达式了,下面贴上代码:
import java.math.BigInteger;
public class Task3_3 {
public static void main(String[] args) {
// TODO Auto-generated method stub
BigInteger bignum1 = new BigInteger("1");
BigInteger bignum2 = new BigInteger("0");
int n=1;
while(n<=100) {
bignum1=bignum1.multiply(BigInteger.valueOf(n));
bignum2=bignum2.add(bignum1);
n++;
}
System.out.println(bignum2.toString());
}
}
这个程序中,笔者创建了两个BigInteger的对象bignum1和bignum2,前者用于存储阶乘的结果,后者存储累加的结果,对于这两个变量的初始化可以通过上面提到的构造函数,以字符串转换的方式实现初始化:
BigInteger bignum1 = new BigInteger("1");
BigInteger bignum2 = new BigInteger("0");
为了提高程序执行的效率,根据题目的特点,没有使用传统的重复计算阶乘的方法,因为我们注意到,当计算n!时实际上就等于是(n-1)!*n而 (n-1)!前面已经计算过了,我们就没有必要再去计算一遍了,所以可以重复利用前一步计算的结果,每乘一个数就把前面的结果加一遍,通过一层循环就可以计算出结果,从而大大减小程序的时间复杂度,代码实现如下:
//重复利用前(n-1)次的计算结果以降低程序的时间复杂度
int n=1;
while(n<=100) {
bignum1=bignum1.multiply(BigInteger.valueOf(n));
bignum2=bignum2.add(bignum1);
n++;
}
最后在打印输出的时候将bignum2转换成字符串后直接输出即可:
System.out.println(bignum2.toString());
最后计算的结果就是这么一个超级天文数字:
94269001683709979260859834124473539872070722613982672442938359305624
67822347950602340029409359913646698660912434743264762282687003822055
6442336528920420940313