Java 中的非常大的斐波那契数列
Very Large Fibonacci in Java
我正在尝试快速计算大的斐波那契数列。这是我的代码。对于超过 100 万的数字,它非常慢,如何改进?
public static BigInteger fib(BigInteger n) {
int k = n.intValue();
BigInteger ans = null;
if(k == 0) {
ans = new BigInteger("0");
} else if(Math.abs(k) <= 2) {
ans = new BigInteger("1");
} else {
BigInteger km1 = new BigInteger("1");
BigInteger km2 = new BigInteger("1");
for(int i = 3; i <= Math.abs(k); ++i) {
ans = km1.add(km2);
km2 = km1;
km1 = ans;
}
}
if(k<0 && k%2==0) { ans = ans.negate(); }
return ans;
}
比奈的表现很好。谢谢你们!
一种方法是计算 2x2 矩阵的 (N-1)th
次方:
A = ((1, 1), (1, 0))
然后我们有
Fib(n) = A^(n-1)[0][0], for n >= 1
矩阵 A
的幂可以使用 Exponentiation by squaring
高效计算
static void multiply(BigInteger m[][], BigInteger n[][]) {
BigInteger a = (m[0][0].multiply(n[0][0])).add(m[0][1].multiply(n[1][0]));
BigInteger b = (m[0][0].multiply(n[0][1])).add(m[0][1].multiply(n[1][1]));
BigInteger c = (m[1][0].multiply(n[0][0])).add(m[1][1].multiply(n[0][1]));
BigInteger d = (m[1][0].multiply(n[0][1])).add(m[1][1].multiply(n[1][1]));
m[0][0] = a;
m[0][1] = b;
m[1][0] = c;
m[1][1] = d;
}
static void fib(int x) {
BigInteger m[][] = new BigInteger[2][2];
m[0][0] = new BigInteger("1");
m[0][1] = new BigInteger("1"); //f1
m[1][0] = new BigInteger("1");
m[1][1] = new BigInteger("0");
BigInteger n[][] = new BigInteger[2][2];
n[0][0] = new BigInteger("1");
n[0][1] = new BigInteger("1"); //f1
n[1][0] = new BigInteger("1");
n[1][1] = new BigInteger("0");
int i = x;
ArrayList <Integer> a = new ArrayList<>();
while (i != 1) {
if (i%2 == 0) {
a.add(0);
i = i / 2;
} else {
a.add(1);
i = i / 2;
}
}
for (int j = a.size() - 1; j >= 0 ; j--) {
if (a.get(j) == 0) {
multiply(m, m);
} else {
multiply(m, m);
multiply(m, n);
}
}
System.out.println(m[1][0]);
}
我正在尝试快速计算大的斐波那契数列。这是我的代码。对于超过 100 万的数字,它非常慢,如何改进?
public static BigInteger fib(BigInteger n) {
int k = n.intValue();
BigInteger ans = null;
if(k == 0) {
ans = new BigInteger("0");
} else if(Math.abs(k) <= 2) {
ans = new BigInteger("1");
} else {
BigInteger km1 = new BigInteger("1");
BigInteger km2 = new BigInteger("1");
for(int i = 3; i <= Math.abs(k); ++i) {
ans = km1.add(km2);
km2 = km1;
km1 = ans;
}
}
if(k<0 && k%2==0) { ans = ans.negate(); }
return ans;
}
比奈的表现很好。谢谢你们!
一种方法是计算 2x2 矩阵的 (N-1)th
次方:
A = ((1, 1), (1, 0))
然后我们有
Fib(n) = A^(n-1)[0][0], for n >= 1
矩阵 A
的幂可以使用 Exponentiation by squaring
static void multiply(BigInteger m[][], BigInteger n[][]) {
BigInteger a = (m[0][0].multiply(n[0][0])).add(m[0][1].multiply(n[1][0]));
BigInteger b = (m[0][0].multiply(n[0][1])).add(m[0][1].multiply(n[1][1]));
BigInteger c = (m[1][0].multiply(n[0][0])).add(m[1][1].multiply(n[0][1]));
BigInteger d = (m[1][0].multiply(n[0][1])).add(m[1][1].multiply(n[1][1]));
m[0][0] = a;
m[0][1] = b;
m[1][0] = c;
m[1][1] = d;
}
static void fib(int x) {
BigInteger m[][] = new BigInteger[2][2];
m[0][0] = new BigInteger("1");
m[0][1] = new BigInteger("1"); //f1
m[1][0] = new BigInteger("1");
m[1][1] = new BigInteger("0");
BigInteger n[][] = new BigInteger[2][2];
n[0][0] = new BigInteger("1");
n[0][1] = new BigInteger("1"); //f1
n[1][0] = new BigInteger("1");
n[1][1] = new BigInteger("0");
int i = x;
ArrayList <Integer> a = new ArrayList<>();
while (i != 1) {
if (i%2 == 0) {
a.add(0);
i = i / 2;
} else {
a.add(1);
i = i / 2;
}
}
for (int j = a.size() - 1; j >= 0 ; j--) {
if (a.get(j) == 0) {
multiply(m, m);
} else {
multiply(m, m);
multiply(m, n);
}
}
System.out.println(m[1][0]);
}