Your Math.pow(phi, n) too big (infinity), double cannot save it, use BigDecimal instead.
How about flow:
static BigInteger getFib(int n) { BigDecimal x1 = new BigDecimal((1 + Math.sqrt(5)) / 2); BigDecimal x2 = new BigDecimal((1 - Math.sqrt(5)) / 2); return x1.pow(n).subtract(x2.pow(n)) .divide(new BigDecimal(Math.sqrt(5))).toBigInteger(); }
according to the formula: 
UPDATE: the above path is incorrect because Math.sqrt (5) is not accurate enough as the comment said. I tried to more accurately derive sqrt (5) using the Netown method and found out that x1.pow(n).subtract(x2.pow(n)).divide(...) takes a very long time, it takes 30 seconds for n = 200 on my computer.
I think the recursive path with the cache is slower:
public static void main(String[] args) { long start = System.nanoTime(); System.out.println(fib(2000)); long end = System.nanoTime(); System.out.println("elapsed:"+ (TimeUnit.NANOSECONDS.toMillis(end - start)) + " ms"); } private static Map<Integer, BigInteger> cache = new HashMap<Integer, BigInteger>(); public static BigInteger fib(int n) { BigInteger bi = cache.get(n); if (bi != null) { return bi; } if (n <= 1) { return BigInteger.valueOf(n); } else { bi = fib(n - 1).add(fib(n - 2)); cache.put(n, bi); return bi; } }
He spent 7 ms on my computer for n = 2000.
source share