一、斐波那契数列是什么?
这里借鉴百度百科一下下:
- 斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家莱昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、
- 在数学上,斐波那契数列以如下被以递推的方法定义:F(0)=0,F(1)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 2,n∈ N*)
- 在现代物理、准晶体结构、化学等领域,斐波纳契数列都有直接的应用,为此,美国数学会从 1963年起出版了以《斐波纳契数列季刊》为名的一份数学杂志,用于专门刊载这方面的研究成果。
很明显:这个数列从第3项开始,每一项都等于前两项之和
二、java代码实现:当输入n时,会获取斐波那契数列的第n个数的值。
- 递归实现:
这里可以很明显看出,通过递归第50个数已经用时31秒多,效率实在太低了。
int的取值范围有限,最大值为 (2^32)-1 = 2147483647,值太大时会发生取值范围溢出的情况。
可以换成Long类型,不过溢出也是迟早的事情。
public class FibonacciTest {
public static void main(String[] args) {
// 获取当前时间戳
long currentTimeMillis1 = System.currentTimeMillis();
// 调用阶乘方法实现斐波那契数列
System.out.println("第50个数是: " + fibonacci(50));
// 获取计算过的当前时间戳
long currentTimeMillis2 = System.currentTimeMillis();
// 获取结果用时多少
System.out.println("递归实现用时" + (currentTimeMillis2 - currentTimeMillis1) + "毫秒");
}
// 前两个数比较特殊
public static int fibonacci(int n) {
if(n == 1) {
// 第一个数给定为0,当然也可以指定别的数字
return 0;
}else if (n == 2){
// 第二个数给定为1,当然也可以指定别的数字
return 1;
}else if (n > 2){
return fibonacci(n-1) + fibonacci(n-2);
}else {
// 如果输入的n为负数,返回-1
return -1;
}
}
}
- for循环实现:
这里是用的Long类型的,计算第50个数只用了2毫秒,这个效率就很nice了!!!不过再计算后面的数还是会出现溢出的情况
public class FibonacciTest {
public static void main(String[] args) {
// 获取当前时间戳
long currentTimeMillis1 = System.currentTimeMillis();
// 调用for循环方法实现斐波那契数列
System.out.println(fibonacci(50));
// 获取计算过的当前时间戳
long currentTimeMillis2 = System.currentTimeMillis();
// 获取结果用时多少
System.out.println("for循环用时" + (currentTimeMillis2 - currentTimeMillis1) + "毫秒");
}
// 前两个数比较特殊
public static Long fibonacci(int n) {
if (n == 1){
// 第一个数给定为0,当然也可以指定别的数字
return 0L;
}else if (n == 2){
// 第二个数给定为1,当然也可以指定别的数字
return 1L;
}else if (n > 2){
//定义三个Long类型整数,first表示指定的第一个数,second表示指定的第二个数,sum表示第n个数
long first =0L, second= 1L, sum =0L;
// 前两个数没有规律,直接给定,所以不参加循环
for (int i = 0; i < n - 2; i++) {
// 根据第三个数的值等于前两个数的和的规律
sum = first + second;
//第2个数的值赋值给第1个数
first = second;
//第3个数的值赋值给第2个数
second = sum;
System.out.println("第" + i + "个数为: " + sum);
}
return sum;
}else {
// 如果输入的n为负数,返回-1
return -1L;
}
}
}
- 接下来完善一下取值溢出的问题:
BigInteger类型的数字范围较Integer,Long类型的数字范围要大得多,它支持任意精度的整数,也就是说在运算中 BigInteger 类型可以准确地表示任何大小的整数值而不会丢失任何信息。
import java.math.BigInteger;
public class FibonacciTest {
public static void main(String[] args) {
// 获取当前时间戳
long currentTimeMillis1 = System.currentTimeMillis();
// 调用for循环方法实现斐波那契数列
System.out.println(fibonacci(500));
// 获取计算过的当前时间戳
long currentTimeMillis2 = System.currentTimeMillis();
// 获取结果用时多少
System.out.println("for循环实现用时" + (currentTimeMillis2 - currentTimeMillis1) + "毫秒");
}
// 前两个数比较特殊
public static BigInteger fibonacci(int n) {
// 实例化BigInteger
BigInteger bigInteger = new BigInteger(String.valueOf(n));
if (n == 1) {
// 第一个数给定为0,当然也可以指定别的数字
return BigInteger.valueOf(0);
} else if (n == 2) {
// 第二个数给定为1,当然也可以指定别的数字
return BigInteger.valueOf(1);
} else if (n > 2) {
//定义三个long类型整数,first表示指定的第一个数,second表示指定的第二个数,sum表示第n个数
BigInteger first = BigInteger.valueOf(0),
second = BigInteger.valueOf(1),
sum = BigInteger.valueOf(0);
// 前两个数没有规律,直接给定,所以不参加循环
for (int i = 0; i < n - 2; i++) {
// 根据第三个数的值等于前两个数的和的规律
sum = first.add(second);
//第2个数的值赋值给第1个数
first = second;
//第3个数的值赋值给第2个数
second = sum;
System.out.println("第" + i + "个数为: " + sum);
}
return sum;
} else {
// 如果输入的n为负数,返回-1
return BigInteger.valueOf(-1);
}
}
}