Open In App
Related Articles

Fast Doubling method to find the Nth Fibonacci number

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Report issue
Report

Given an integer N, the task is to find the N-th Fibonacci numbers.
Examples: 

Input: N = 3 
Output:
Explanation: 
F(1) = 1, F(2) = 1 
F(3) = F(1) + F(2) = 2 
Input: N = 6 
Output:
 

Approach:  

  • The Matrix Exponentiation Method is already discussed before. The Doubling Method can be seen as an improvement to the matrix exponentiation method to find the N-th Fibonacci number although it doesn’t use matrix multiplication itself.
     
  • The Fibonacci recursive sequence is given by 
     
F(n+1) = F(n) + F(n-1)
  • The Matrix Exponentiation method uses the following formula

        \[ \begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix}^n = \begin{bmatrix} F_{n+1} & F_n \\ F_n & F_{n-1} \end{bmatrix} \]


     
  • The method involves costly matrix multiplication and moreover Fn is redundantly computed twice.
    On the other hand, Fast Doubling Method is based on two basic formulas: 
     
F(2n) = F(n)[2F(n+1) – F(n)]
F(2n + 1) = F(n)2+F(n+1)2
  • Here is a short explanation of the above results:
     

Start with: 
F(n+1) = F(n) + F(n-1) & 
F(n) = F(n) 
It can be rewritten in the matrix form as: 

    \[ \begin{bmatrix} F(n+1) \\ F(n) \end{bmatrix} = \begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix} \begin{bmatrix} F(n) \\ F(n-1) \end{bmatrix} \] \[\quad\enspace= \begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix}^2 \begin{bmatrix} F(n-1) \\ F(n-2) \end{bmatrix} \] \quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\enspace\enspace\thinspace......\\ \[= \begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix}^n \begin{bmatrix} F(1) \\ F(0) \end{bmatrix} \]


For doubling, we just plug in “2n” into the formula:

    \[ \begin{bmatrix} F(2n+1) \\ F(2n) \end{bmatrix} = \begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix}^{2n} \begin{bmatrix} F(1) \\ F(0) \end{bmatrix} \] \[\quad\enspace= \begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix}^n \begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix}^n \begin{bmatrix} F(1) \\ F(0) \end{bmatrix} \] \[\quad\enspace= \begin{bmatrix} F(n+1) & F(n) \\ F(n) & F(n-1) \end{bmatrix} \begin{bmatrix} F(n+1) & F(n) \\ F(n) & F(n-1) \end{bmatrix} \begin{bmatrix} F(1) \\ F(0) \end{bmatrix} \] \[\quad\enspace= \begin{bmatrix} F(n+1)^2 + F(n)^2 \\ F(n)F(n+1) + F(n)F(n-1) \end{bmatrix} \]


Substituting F(n-1) = F(n+1)- F(n) and after simplification we get, 

    \[ \begin{bmatrix} F(2n+1) \\ F(2n) \end{bmatrix} = \begin{bmatrix} F(n+1)^2 + F(n)^2 \\ 2F(n+1)F(n) - F(n)^2 \end{bmatrix} \]


 


Below is the implementation of the above approach:
 

C++

// C++ program to find the Nth Fibonacci
// number using Fast Doubling Method
#include <bits/stdc++.h>
using namespace std;
 
int a, b, c, d;
#define MOD 1000000007
 
// Function calculate the N-th fibonacci
// number using fast doubling method
void FastDoubling(int n, int res[])
{
    // Base Condition
    if (n == 0) {
        res[0] = 0;
        res[1] = 1;
        return;
    }
    FastDoubling((n / 2), res);
 
    // Here a = F(n)
    a = res[0];
 
    // Here b = F(n+1)
    b = res[1];
 
    c = 2 * b - a;
 
    if (c < 0)
        c += MOD;
 
    // As F(2n) = F(n)[2F(n+1) – F(n)]
    // Here c  = F(2n)
    c = (a * c) % MOD;
 
    // As F(2n + 1) = F(n)^2 + F(n+1)^2
    // Here d = F(2n + 1)
    d = (a * a + b * b) % MOD;
 
    // Check if N is odd
    // or even
    if (n % 2 == 0) {
        res[0] = c;
        res[1] = d;
    }
    else {
        res[0] = d;
        res[1] = c + d;
    }
}
 
// Driver code
int main()
{
    int N = 6;
    int res[2] = { 0 };
 
    FastDoubling(N, res);
 
    cout << res[0] << "\n";
    return 0;
}

                    

Java

// Java program to find the Nth Fibonacci
// number using Fast Doubling Method
class GFG{
 
// Function calculate the N-th fibonacci
// number using fast doubling method
static void FastDoubling(int n, int []res)
{
    int a, b, c, d;
    int MOD = 1000000007;
     
    // Base Condition
    if (n == 0)
    {
        res[0] = 0;
        res[1] = 1;
        return;
    }
    FastDoubling((n / 2), res);
 
    // Here a = F(n)
    a = res[0];
 
    // Here b = F(n+1)
    b = res[1];
 
    c = 2 * b - a;
 
    if (c < 0)
        c += MOD;
 
    // As F(2n) = F(n)[2F(n+1) – F(n)]
    // Here c = F(2n)
    c = (a * c) % MOD;
 
    // As F(2n + 1) = F(n)^2 + F(n+1)^2
    // Here d = F(2n + 1)
    d = (a * a + b * b) % MOD;
 
    // Check if N is odd
    // or even
    if (n % 2 == 0)
    {
        res[0] = c;
        res[1] = d;
    }
    else
    {
        res[0] = d;
        res[1] = c + d;
    }
}
 
// Driver code
public static void main(String []args)
{
    int N = 6;
    int res[] = new int[2];
 
    FastDoubling(N, res);
 
    System.out.print(res[0]);
}
}
 
// This code is contributed by rock_cool

                    

Python3

# Python3 program to find the Nth Fibonacci
# number using Fast Doubling Method
MOD = 1000000007
 
# Function calculate the N-th fibonacci
# number using fast doubling method
def FastDoubling(n, res):
     
    # Base Condition
    if (n == 0):
        res[0] = 0
        res[1] = 1
        return
         
    FastDoubling((n // 2), res)
 
    # Here a = F(n)
    a = res[0]
 
    # Here b = F(n+1)
    b = res[1]
 
    c = 2 * b - a
 
    if (c < 0):
        c += MOD
 
    # As F(2n) = F(n)[2F(n+1) – F(n)]
    # Here c = F(2n)
    c = (a * c) % MOD
 
    # As F(2n + 1) = F(n)^2 + F(n+1)^2
    # Here d = F(2n + 1)
    d = (a * a + b * b) % MOD
 
    # Check if N is odd
    # or even
    if (n % 2 == 0):
        res[0] = c
        res[1] = d
    else :
        res[0] = d
        res[1] = c + d
     
# Driver code
N = 6
res = [0] * 2
 
FastDoubling(N, res)
 
print(res[0])
     
# This code is contributed by divyamohan123

                    

C#

// C# program to find the Nth Fibonacci
// number using Fast Doubling Method
using System;
class GFG{
 
// Function calculate the N-th fibonacci
// number using fast doubling method
static void FastDoubling(int n, int []res)
{
    int a, b, c, d;
    int MOD = 1000000007;
     
    // Base Condition
    if (n == 0)
    {
        res[0] = 0;
        res[1] = 1;
        return;
    }
    FastDoubling((n / 2), res);
 
    // Here a = F(n)
    a = res[0];
 
    // Here b = F(n+1)
    b = res[1];
 
    c = 2 * b - a;
 
    if (c < 0)
        c += MOD;
 
    // As F(2n) = F(n)[2F(n+1) – F(n)]
    // Here c = F(2n)
    c = (a * c) % MOD;
 
    // As F(2n + 1) = F(n)^2 + F(n+1)^2
    // Here d = F(2n + 1)
    d = (a * a + b * b) % MOD;
 
    // Check if N is odd
    // or even
    if (n % 2 == 0)
    {
        res[0] = c;
        res[1] = d;
    }
    else
    {
        res[0] = d;
        res[1] = c + d;
    }
}
 
// Driver code
public static void Main()
{
    int N = 6;
    int []res = new int[2];
 
    FastDoubling(N, res);
 
    Console.Write(res[0]);
}
}
 
// This code is contributed by Code_Mech

                    

Javascript

<script>
 
    // Javascript program to find the Nth Fibonacci
      // number using Fast Doubling Method
     
    let a, b, c, d;
    let MOD = 1000000007;
 
    // Function calculate the N-th fibonacci
    // number using fast doubling method
    function FastDoubling(n, res)
    {
        // Base Condition
        if (n == 0) {
            res[0] = 0;
            res[1] = 1;
            return;
        }
        FastDoubling(parseInt(n / 2, 10), res);
 
        // Here a = F(n)
        a = res[0];
 
        // Here b = F(n+1)
        b = res[1];
 
        c = 2 * b - a;
 
        if (c < 0)
            c += MOD;
 
        // As F(2n) = F(n)[2F(n+1) – F(n)]
        // Here c  = F(2n)
        c = (a * c) % MOD;
 
        // As F(2n + 1) = F(n)^2 + F(n+1)^2
        // Here d = F(2n + 1)
        d = (a * a + b * b) % MOD;
 
        // Check if N is odd
        // or even
        if (n % 2 == 0) {
            res[0] = c;
            res[1] = d;
        }
        else {
            res[0] = d;
            res[1] = c + d;
        }
    }
 
    let N = 6;
    let res = new Array(2);
    res.fill(0);
   
    FastDoubling(N, res);
   
    document.write(res[0]);
     
</script>

                    

Output
8

Time Complexity: Repeated squaring reduces time from linear to logarithmic . Hence, with constant time arithmetic, the time complexity is O(log n).
Auxiliary Space: O(n).

Iterative Version

We can implement iterative version of above method, by initializing array with two elements f = [F(0), F(1)] = [0, 1] and iteratively constructing F(n), on every step we will transform f into [F(2i), F(2i+1)] or [F(2i+1), F(2i+2)] , where i corresponds to the current value of i stored in f = [F(i), F(i+1)].

Approach:

  • Create array with two elements f = [0, 1] , which represents [F(0), F(1)] .
  • For finding F(n), iterate over binary representation of n from left to right, let kth bit from left be bk .
  • Iteratively apply the below steps for all bits in n .
  • Using bk we will decide whether to transform f = [F(i), F(i+1)] into [F(2i), F(2i+1)] or [F(2i+1), F(2i+2)] .
if bk == 0:
f = [F(2i), F(2i+1)] = [F(i){2F(i+1)-F(i)}, F(i+1)2+F(i)2]
if bk == 1:
f = [F(2i+1), F(2i+2)] = [F(i+1)2+F(i)2, F(i+1){2F(i)+F(i+1)}]

where,
F(i) and F(i+1) are current values stored in f.
  • return f[0] .
Example:
for n = 13 = (1101)2
b = 1 1 0 1
[F(0), F(1)] -> [F(1), F(2)] -> [F(3), F(4)] -> [F(6), F(7)] -> [F(13), F(14)]
[0, 1] -> [1, 1] -> [2, 3] -> [8, 13] -> [233, 377]

Below is the implementation of the above approach:

C++

// C++ program to find the Nth Fibonacci
// number using Fast Doubling Method iteratively
 
#include <bitset>
#include <iostream>
#include <string>
 
using namespace std;
 
// helper function to get binary string
string decimal_to_bin(int n)
{
    // use bitset to get binary string
    string bin = bitset<sizeof(int) * 8>(n).to_string();
    auto loc = bin.find('1');
    // remove leading zeros
    if (loc != string::npos)
        return bin.substr(loc);
    return "0";
}
 
// computes fib(n) iteratively using fast doubling method
long long fastfib(int n)
{
    string bin_of_n
        = decimal_to_bin(n); // binary string of n
 
    long long f[] = { 0, 1 }; // [F(i), F(i+1)] => i=0
 
    for (auto b : bin_of_n) {
        long long f2i1
            = f[1] * f[1] + f[0] * f[0]; // F(2i+1)
        long long f2i = f[0] * (2 * f[1] - f[0]); // F(2i)
 
        if (b == '0') {
            f[0] = f2i; // F(2i)
            f[1] = f2i1; // F(2i+1)
        }
        else {
            f[0] = f2i1; // F(2i+1)
            f[1] = f2i1 + f2i; // F(2i+2)
        }
    }
 
    return f[0];
}
 
int main()
{
    int n = 13;
    long long fib = fastfib(n);
    cout << "F(" << n << ") = " << fib << "\n";
}

                    

Java

// Java program to find the Nth Fibonacci
// number using Fast Doubling Method iteratively
import java.io.*;
 
class GFG {
 
  // Helper function to convert decimal to binary.
  static String convertToBinary(int x)
  {
    int bin = 0;
    int rem, i = 1, step = 1;
 
    while (x != 0) {
      rem = x % 2;
      x = x / 2;
      bin = bin + rem * i;
      i = i * 10;
    }
    return Integer.toString(bin);
  }
 
  // helper function to get binary string
  static String decimal_to_bin(int n)
  {
    // use bitset to get binary string
    String bin = convertToBinary(n);
    int loc = bin.indexOf("1");
     
    // remove leading zeros
    if (loc != -1) {
      return bin.substring(loc);
    }
    return "0";
  }
 
  // computes fib(n) iteratively using fast doubling
  // method
  static int fastfib(int n)
  {
    String bin_of_n
      = decimal_to_bin(n); // binary string of n
 
    int[] f = { 0, 1 }; // [F(i), F(i+1)] => i=0
 
    for (int i = 0; i < bin_of_n.length(); i++) {
      int b = bin_of_n.charAt(i);
      int f2i1 = f[1] * f[1] + f[0] * f[0]; // F(2i+1)
      int f2i = f[0] * (2 * f[1] - f[0]); // F(2i)
 
      if (b == '0') {
        f[0] = f2i; // F(2i)
        f[1] = f2i1; // F(2i+1)
      }
      else {
        f[0] = f2i1; // F(2i+1)
        f[1] = f2i1 + f2i; // F(2i+2)
      }
    }
 
    return f[0];
  }
 
  public static void main(String[] args)
  {
    int n = 13;
    int fib = fastfib(n);
    System.out.print("F(" + n + ") = " + fib);
  }
}
 
// This code is contributed by lokeshmvs21.

                    

Python3

# Python3 program to find the Nth Fibonacci
# number using Fast Doubling Method iteratively
 
 
def fastfib(n):
    """computes fib(n) iteratively using fast doubling method"""
    bin_of_n = bin(n)[2:]  # binary string of n
    f = [0, 1# [F(i), F(i+1)] => i=0
 
    for b in bin_of_n:
        f2i1 = f[1]**2 + f[0]**2  # F(2i+1)
        f2i = f[0]*(2*f[1]-f[0])  # F(2i)
 
        if b == '0':
            f[0], f[1] = f2i, f2i1  # [F(2i), F(2i+1)]
        else:
            f[0], f[1] = f2i1, f2i1+f2i  # [F(2i+1), F(2i+2)]
 
    return f[0]
 
 
n = 13
fib = fastfib(n)
print(f'F({n}) =', fib)

                    

C#

using System;
using System.Collections.Generic;
 
// C# program to find the Nth Fibonacci
// number using Fast Doubling Method iteratively
public class GFG {
 
  // Helper function to convert decimal to binary.
  public static string convertToBinary(int x)
  {
    int bin = 0;
    int rem, i = 1, step = 1;
 
    while (x != 0) {
      rem = x % 2;
      x = x / 2;
      bin = bin + rem * i;
      i = i * 10;
    }
    return bin.ToString();
  }
 
  // helper function to get binary string
  public static string decimal_to_bin(int n)
  {
    // use bitset to get binary string
    string bin = convertToBinary(n);
    int loc = bin.IndexOf('1');
 
    // remove leading zeros
    if (loc != -1) {
      return bin.Substring(loc);
    }
    return "0";
  }
 
  // computes fib(n) iteratively using fast doubling
  // method
  public static int fastfib(int n)
  {
    string bin_of_n
      = decimal_to_bin(n); // binary string of n
 
    int[] f = { 0, 1 }; // [F(i), F(i+1)] => i=0
 
    for (int i = 0; i < bin_of_n.Length; i++) {
      int b = bin_of_n[i];
      int f2i1 = f[1] * f[1] + f[0] * f[0]; // F(2i+1)
      int f2i = f[0] * (2 * f[1] - f[0]); // F(2i)
 
      if (b == '0') {
        f[0] = f2i; // F(2i)
        f[1] = f2i1; // F(2i+1)
      }
      else {
        f[0] = f2i1; // F(2i+1)
        f[1] = f2i1 + f2i; // F(2i+2)
      }
    }
 
    return f[0];
  }
 
  static public void Main()
  {
 
    int n = 13;
    int fib = fastfib(n);
    Console.WriteLine("F(" + n + ") = " + fib);
  }
}
 
// This code is contributed by akashish__

                    

Javascript

// JavaScript program to find the Nth Fibonacci
// number using Fast Doubling Method iteratively
 
// Helper function to convert decimal to binary.
function convertToBinary(x) {
    let bin = 0;
    let rem, i = 1, step = 1;
    while (x != 0) {
        rem = x % 2;
        x = parseInt(x / 2);
        bin = bin + rem * i;
        i = i * 10;
    }
    // let myArr = Array.from(String(bin).split(""));
    return bin.toString();
}
 
// helper function to get binary string
function decimal_to_bin(n)
{
    // use bitset to get binary string
    let bin = convertToBinary(n);
    let loc = bin.indexOf('1');
    // remove leading zeros
    if (loc != -1)
        return bin.substring(loc);
    return "0";
}
 
// computes fib(n) iteratively using fast doubling method
function fastfib(n)
{
    let bin_of_n = decimal_to_bin(n); // binary string of n
 
    let f = [0, 1]; // [F(i), F(i+1)] => i=0
 
    for(let i = 0; i < bin_of_n.length; i++){
        let b = bin_of_n[i];
        let f2i1 = f[1] * f[1] + f[0] * f[0]; // F(2i+1)
        let f2i = f[0] * (2 * f[1] - f[0]); // F(2i)
 
        if (b == '0') {
            f[0] = f2i; // F(2i)
            f[1] = f2i1; // F(2i+1)
        }
        else {
            f[0] = f2i1; // F(2i+1)
            f[1] = f2i1 + f2i; // F(2i+2)
        }
    }
 
    return f[0];
}
 
let n = 13;
let fib = fastfib(n);
console.log("F(",n,") =", fib);
 
// The code is contributed by Gautam goel (gautamgoel962)

                    

Output
F(13) = 233

Time Complexity: We are iterating over a binary string of length n and doing constant time arithmetic operations for each digit, so the time complexity is O(n).

Auxiliary Space: We are storing two elements in f (which is a constant cost), and the binary representation of the number (which has a cost of O(n)) so space complexity is O(n). We could reduce this down to O(1) if we didn’t convert the number to a string, but instead used the bits of the number to iterate through .



Last Updated : 02 Nov, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads