n > 46 Java 的斐波那契数列
Fibonacci sequence for n > 46 Java
我有以下代码,它为 n < 47 提供了正确的值。
public static int fib(int n) {
int nthTerm = 0;
if (n == 2)
nthTerm = 1;
else {
double goldenRatio = (1 + Math.sqrt(5)) / 2;
nthTerm = (int) (Math.round(Math.pow(goldenRatio, n)
- Math.pow(1 - goldenRatio, n)) / Math.sqrt(5));
if (n % 2 == 1 && n < 45)
nthTerm++;
}
return nthTerm;
}
n > 46 的任何值都超出了 int 范围。我怎样才能使这种方法适用于 n > 46?
P.S。我知道 BigInteger,但不是很擅长,所以我也希望能有一个使用 BigInteger 的示例。
使用 long
而不是 int
,并且记得将值从 Math.round()
转换为 long
(通过编写 (long) Math.round(...)
就像你投射到 int
) .
你不能使用 int
的原因是因为 fib(47)
是 2971215073
溢出了 Java 的签名 32 位 int
(231-1). You could use a memoization optimization to implement it with BigInteger
喜欢,
private static Map<Integer, BigInteger> memo = new HashMap<>();
static {
memo.put(0, BigInteger.ZERO);
memo.put(1, BigInteger.ONE);
}
public static BigInteger fib(int n) {
if (memo.containsKey(n)) {
return memo.get(n);
}
BigInteger v = fib(n - 2).add(fib(n - 1));
memo.put(n, v);
return v;
}
如果使用long
,则完美支持1000以上的范围;但是如果你想支持所有可能的值,那么你需要使用 BigInteger
.
示例使用 long
:
public static long fib(int n)
{
long f0 = 1;
long f1 = 1;
long c = 2;
while(c < n)
{
long tmp = f0+f1;
f0 = f1;
f1 = tmp;
c++;
}
return f1;
}
您可以使用它来将代码转换为 BigInteger。
package your.pack
import java.math.BigDecimal;
import java.math.BigInteger;
/**
* Created on 3/6/16.
*/
public class Fibonacci {
private static BigDecimal goldenRatio = new BigDecimal((1 + Math.sqrt(5)) / 2);
private static BigDecimal goldenRatioMin1 = goldenRatio.subtract(BigDecimal.ONE);
private static BigDecimal sqrt5 = new BigDecimal(Math.sqrt(5));
private static BigInteger fib(int n) {
BigInteger nthTerm = new BigInteger("0");
if (n == 2)
nthTerm = BigInteger.ONE;
else {
BigDecimal minResult = goldenRatio.pow(n).subtract(goldenRatioMin1.pow(n));
nthTerm = minResult.divide(sqrt5,0).toBigInteger();
if (n % 2 == 1 && n < 45){
nthTerm = nthTerm.add(BigInteger.ONE);
}
}
return nthTerm;
}
private static int fib2(int n) {
int nthTerm = 0;
if (n == 2)
nthTerm = 1;
else {
double goldenRatio = (1 + Math.sqrt(5)) / 2;
nthTerm = (int) (Math.round(Math.pow(goldenRatio, n)
- Math.pow(1 - goldenRatio, n)) / Math.sqrt(5));
if (n % 2 == 1 && n < 45)
nthTerm++;
}
return nthTerm;
}
public static void main(String []args){
System.out.println(
fib(47)
);
}
}
方法fib2是你的代码,fib是转换成BigInteger。干杯
我有以下代码,它为 n < 47 提供了正确的值。
public static int fib(int n) {
int nthTerm = 0;
if (n == 2)
nthTerm = 1;
else {
double goldenRatio = (1 + Math.sqrt(5)) / 2;
nthTerm = (int) (Math.round(Math.pow(goldenRatio, n)
- Math.pow(1 - goldenRatio, n)) / Math.sqrt(5));
if (n % 2 == 1 && n < 45)
nthTerm++;
}
return nthTerm;
}
n > 46 的任何值都超出了 int 范围。我怎样才能使这种方法适用于 n > 46?
P.S。我知道 BigInteger,但不是很擅长,所以我也希望能有一个使用 BigInteger 的示例。
使用 long
而不是 int
,并且记得将值从 Math.round()
转换为 long
(通过编写 (long) Math.round(...)
就像你投射到 int
) .
你不能使用 int
的原因是因为 fib(47)
是 2971215073
溢出了 Java 的签名 32 位 int
(231-1). You could use a memoization optimization to implement it with BigInteger
喜欢,
private static Map<Integer, BigInteger> memo = new HashMap<>();
static {
memo.put(0, BigInteger.ZERO);
memo.put(1, BigInteger.ONE);
}
public static BigInteger fib(int n) {
if (memo.containsKey(n)) {
return memo.get(n);
}
BigInteger v = fib(n - 2).add(fib(n - 1));
memo.put(n, v);
return v;
}
如果使用long
,则完美支持1000以上的范围;但是如果你想支持所有可能的值,那么你需要使用 BigInteger
.
示例使用 long
:
public static long fib(int n)
{
long f0 = 1;
long f1 = 1;
long c = 2;
while(c < n)
{
long tmp = f0+f1;
f0 = f1;
f1 = tmp;
c++;
}
return f1;
}
您可以使用它来将代码转换为 BigInteger。
package your.pack
import java.math.BigDecimal;
import java.math.BigInteger;
/**
* Created on 3/6/16.
*/
public class Fibonacci {
private static BigDecimal goldenRatio = new BigDecimal((1 + Math.sqrt(5)) / 2);
private static BigDecimal goldenRatioMin1 = goldenRatio.subtract(BigDecimal.ONE);
private static BigDecimal sqrt5 = new BigDecimal(Math.sqrt(5));
private static BigInteger fib(int n) {
BigInteger nthTerm = new BigInteger("0");
if (n == 2)
nthTerm = BigInteger.ONE;
else {
BigDecimal minResult = goldenRatio.pow(n).subtract(goldenRatioMin1.pow(n));
nthTerm = minResult.divide(sqrt5,0).toBigInteger();
if (n % 2 == 1 && n < 45){
nthTerm = nthTerm.add(BigInteger.ONE);
}
}
return nthTerm;
}
private static int fib2(int n) {
int nthTerm = 0;
if (n == 2)
nthTerm = 1;
else {
double goldenRatio = (1 + Math.sqrt(5)) / 2;
nthTerm = (int) (Math.round(Math.pow(goldenRatio, n)
- Math.pow(1 - goldenRatio, n)) / Math.sqrt(5));
if (n % 2 == 1 && n < 45)
nthTerm++;
}
return nthTerm;
}
public static void main(String []args){
System.out.println(
fib(47)
);
}
}
方法fib2是你的代码,fib是转换成BigInteger。干杯