黑马程序员技术交流社区

标题: 由兔子问题引起的BigInteger学习 [打印本页]

作者: 李孝志    时间: 2016-10-1 11:04
标题: 由兔子问题引起的BigInteger学习
       前几天与我同学说起兔子问题(斐波那契数列),他问我第10000个月的兔子数量是多少?然后我就用JAVA开始算。      
       首先用int类型方法
[Java] 纯文本查看 复制代码
public class Tuzi1 {
        public static void main(String[] args) {
                int month = 46;   
                long start = System.currentTimeMillis();                                                                                                                                       
                System.out.println("第"+month+"个月兔子总数为"+fun(month));
                long end = System.currentTimeMillis();
                System.out.println("程序运行时间" + (end-start) + "毫秒");
        }
        private static int fun(int n){
                if(n==1 || n==2)
                   return 1;
                else
                   return fun(n-1)+fun(n-2);
        }
}


但是int长度不够。
当month=46是正数1836311903   month=47是兔子的总数量为-1323752223;表示int数据类型(-2147483648~2147483647)范围越界。第47个月的数量是2971215073;
     然后换long类型,这时又出了一个新问题,在程序中用的是fun()方法,使用了递归,当month>50时,程序运行时间变长,所以把代码改为以下:
[AppleScript] 纯文本查看 复制代码
public class Tuzi2 {
        public static void main(String[] args) {
                long start = System.currentTimeMillis();
                long month=1406;  
                long i1=1;//第一个月兔子为一对
                long i2=1;//第二个月兔子为一对
                long i=0;//代表前一个月兔子的对数
                long sum=0; //兔子的总数
                for(long j=3;j<=month;j++){
                        i=i2;//当J=3时,前一个月即为第二个月,故将i2的值给i
                        i2=i+i1;
                        i1=i;
                        sum=sum+i2+2;
                }
                System.out.println("兔子的总数量为"+sum*2);
                long end = System.currentTimeMillis();
                System.out.println(end-start);
        }
}

但是long类型只能计算到month=88(兔子数量5760134388741632578),超过88,又超范围了,改为double类型,但是double
有一个缺点,大的数字用幂表示,只能精确到小数点后面16位,即使是这样也只能计算到month=1406(兔子数量1.6074684786574634E294)。
        这时我一脸蒙逼的样子,没有类型可用了,这时还没网,用手机搜了一下,找到了BigInteger。
BigInteger介绍:不可变的任意精度的整数。所有操作中,都以二进制补码形式表示 BigInteger(如 Java 的基本整数类型)。
        BigInteger 提供所有 Java 的基本整数操作符的对应物,并提供 java.lang.Math 的所有相关方法。
        另外,BigInteger 还提供以下运算:模算术、GCD 计算、质数测试、素数生成、位操作以及一些其他操作。
1.BigInteger属于java.math.BigInteger,包,因此在每次使用前都要导包。使用时不要忘记导包。
2.其构造方法有很多,但现在我用到的是时:
        1).加法: BigInteger add(BigInteger val)
                返回其值为 (this + val) 的 BigInteger
        2).常量:BigInteger.ONE,常量1.
        3).数组:BigInteger[];
3.另外说明BigInteger的数学运算。
        减法:subtract(BigInteger val)返回其值为 (this - val) 的 BigInteger。
        乘法:multiply(BigInteger val)返回其值为 (this * val) 的 BigInteger。
        除法:divide(BigInteger val)返回其值为 (this / val) 的 BigInteger。
        取模:BigInteger remainder(BigInteger val)返回其值为 (this % val) 的 BigInteger。
        注意:其内容进行数学运算时不能直接使用数学运算符进行运算,必须使用其内部方法。
        而且其操作数也必须为BigInteger型。如:two.add(2)就是一种错误的操作,因为2没有变为BigInteger型。

新代码
[Java] 纯文本查看 复制代码
import java.math.BigInteger;
public class Tuzi3 {        
        public static void main(String[] args) {
                long start=System.currentTimeMillis();
                //创建数组
                        int month=1407;   
                BigInteger[] integers = new BigInteger[month];
                //初始化前两个数字
                integers[0] = BigInteger.ONE;
                integers[1] = BigInteger.ONE;
                for (int i = 2; i < month; i++)
                    integers = integers[i - 1].add(integers[i - 2]);
                //打印数组
                BigInteger sum =integers[0];
                for (int i = 0; i < integers.length; i++)
                        sum =integers;               
                System.out.println("第"+ month +"个月兔子数量:" + sum);
                long end=System.currentTimeMillis();
                System.out.println("程序耗时 "+(end-start)+" 毫秒");
        }
}


使用BigInteger,不但能计算出month=10000(用时22毫秒),就是month=20000(用时65毫秒)也可以,因为数据太长,就不写了。

作者: 小明教授    时间: 2016-10-1 11:24
可以的,很强势
作者: 小泥人    时间: 2016-10-1 14:55
BigInteger精度比较高,金融什么的用的比较多
作者: markiyangliu    时间: 2016-10-1 15:18
向学霸致敬!!!!
作者: 喝咖啡的玉米    时间: 2016-10-1 17:09
嗯,想你学习
作者: hysnxdss    时间: 2016-10-1 17:16
自从知道这道题,觉得养兔子比程序员赚钱
作者: songfei    时间: 2016-10-1 21:45
又学到了新知识,
作者: 李春林    时间: 2016-10-6 07:24
学习了!!!!





欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2