programming-examples/java/_Basics/FibonacciSequence.java
2019-11-15 12:59:38 +01:00

136 lines
4.5 KiB
Java

package com.jwetherell.algorithms.sequence;
/**
* In mathematics, the Fibonacci numbers are the numbers in the following integer sequence, called the Fibonacci sequence, and characterized by the fact that every number after the first two is the
* sum of the two preceding ones: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ...
* <p>
*
* https://en.wikipedia.org/wiki/Fibonacci_number
* <br>
* @author Justin Wetherell <phishman3579@gmail.com>
*/
public class FibonacciSequence {
private static final double INVERSE_SQUARE_ROOT_OF_5 = 1 / Math.sqrt(5); // Inverse of the square root of 5
private static final double PHI = (1 + Math.sqrt(5)) / 2; // Golden ratio
private FibonacciSequence() {}
public static final long fibonacciSequenceUsingLoop(int n) {
final long[] array = new long[n + 1];
int counter = 0;
while (counter <= n) {
long r = 0;
if (counter > 1) {
r = array[counter - 1] + array[counter - 2];
} else if (counter == 1) {
r = 1;
}
// If r goes below zero then we have run out of bits in the long
if (r < 0)
throw new IllegalArgumentException("Run out of bits in long, n="+n);
array[counter] = r;
counter++;
}
return array[n];
}
/**
* Recursion with memoization
*/
public static final long fibonacciSequenceUsingRecursion(int n) {
// Using the array to store values already computed
final long[] array = new long[n + 1];
return fibonacciSequenceUsingRecursion(array,n);
}
private static final long fibonacciSequenceUsingRecursion(long[] array, int n) {
if (n == 0 || n == 1)
return n;
// If array already has a value then it has previously been computed
if (array[n] != 0)
return array[n];
final String exception = "Run out of bits in long, n="+n;
final long r1 = fibonacciSequenceUsingRecursion(array, (n - 1));
array[n-1] = r1; // memoization
// If r1 goes below zero then we have run out of bits in the long
if (r1 < 0)
throw new IllegalArgumentException(exception);
final long r2 = fibonacciSequenceUsingRecursion(array, (n - 2));
array[n-2] = r2; // memoization
// If r2 goes below zero then we have run out of bits in the long
if (r2 < 0)
throw new IllegalArgumentException(exception);
final long r = r1 + r2;
// If r goes below zero then we have run out of bits in the long
if (r < 0)
throw new IllegalArgumentException("Run out of bits in long, n="+n);
array[n] = r; // memoization
return r;
}
public static final long fibonacciSequenceUsingMatrixMultiplication(int n) {
// m = [ 1 , 1 ]
// [ 1 , 0 ]
final long[][] matrix = new long[2][2];
matrix[0][0] = 1;
matrix[0][1] = 1;
matrix[1][0] = 1;
matrix[1][1] = 0;
long[][] temp = new long[2][2];
temp[0][0] = 1;
temp[0][1] = 1;
temp[1][0] = 1;
temp[1][1] = 0;
int counter = n;
while (counter > 0) {
temp = multiplyMatrices(matrix, temp);
// Subtract an additional 1 the first time in the loop because the
// first multiplication is actually n -= 2 since it multiplying two matrices
counter -= (counter == n) ? 2 : 1;
}
final long r = temp[0][1];
// If r goes below zero then we have run out of bits in the long
if (r < 0)
throw new IllegalArgumentException("Run out of bits in long, n="+n);
return r;
}
private static final long[][] multiplyMatrices(long[][] A, long[][] B) {
final long a = A[0][0];
final long b = A[0][1];
final long c = A[1][0];
final long d = A[1][1];
final long e = B[0][0];
final long f = B[0][1];
final long g = B[1][0];
final long h = B[1][1];
B[0][0] = a * e + b * g;
B[0][1] = a * f + b * h;
B[1][0] = c * e + d * g;
B[1][1] = c * f + d * h;
return B;
}
public static final long fibonacciSequenceUsingBinetsFormula(int n) {
final long r = (long) Math.floor(Math.pow(PHI, n) * INVERSE_SQUARE_ROOT_OF_5 + 0.5);
// If r hits max value then we have run out of bits in the long
if (r == Long.MAX_VALUE)
throw new IllegalArgumentException("Run out of bits in long, n="+n);
return r;
}
}