4

I have to find the first k digit for all Fibonacci number up to fibonacci sequence 2*10^6.

It is clear that we can not store the value of the fibonacci number in any variable. Even calculating all the fibonacci number itself take huge computational time. So, is there any way just to get the first k digit of fibonacci number without generating the whole number?

  • 1
    Umm, 10^6 is only 1,000,000. There's no need to get fancy with this. – elixenide Oct 03 '15 at 11:20
  • 5
    By "up to fibonacci sequence 2*10^6", do you mean up to the `2*10^6`th fibonacci number, or up to the fibonacci number that is `<= 2*10^6`? – IVlad Oct 03 '15 at 11:24
  • "huge computational time" - why exactly? the sequence has exponential growth. – Karoly Horvath Oct 03 '15 at 11:34
  • 2
    Leftmost or rightmost k digits? – Alireza Oct 03 '15 at 11:49
  • Do you have to compute it to *all* numbers or *any* number? – Juan Lopes Oct 03 '15 at 12:00
  • I don't understand why computing the fibonacci number in the traditional way would be inefficient here. Since you want **all** fibonacci numbers up to the nth item in the sequence, your best case algorithm will be O(n) if you can make the computation of each item constant time. But if you just compute all items sequentially, each item is still constant time to compute (it's just addition of the last two items), and a running tally of the last two values takes constant space to store. What does the ability to get first k digits of arbitrary fibonacci number get you? – Asad Saeeduddin Oct 03 '15 at 13:02
  • @IVlad I want to say upto 2*10^6 th Fibonacci number. – Sourav Bhattacharjee Oct 04 '15 at 11:03
  • @Alireza Leftmost k digits.. – Sourav Bhattacharjee Oct 04 '15 at 11:03
  • `It is clear that we can not store the value of the fibonacci number in any variable.` How so? The computation between two values to output is negligible, the main trick is to keep the values so that base conversion is no issue at all or trivial - BCD or something a bit more fancy (10¹⁰). – greybeard Oct 04 '15 at 17:14

2 Answers2

3

Since you only need the leading digits, an approximation to the Fibonacci number is sufficient. Thus, you can use the closed-form formula for the nth Fibonacci number, which is

Fn = (φn − (−φ)n) / √5, where φ = (1 + √5) / 2 &approx; 1.6180339887

... then round to the desired precision.

Code Whisperer
  • 22,959
  • 20
  • 67
  • 85
user448810
  • 17,381
  • 4
  • 34
  • 59
  • It is okay if we follow traditional fibonacci series.. But if does not start from one.. Let it start from 3 and 5 then? – Sourav Bhattacharjee Oct 04 '15 at 11:06
  • What if this is not about an approximation to the first, say, 1984 digits of the decimal representations of the Fibonacci series, but the exact values? – greybeard Oct 04 '15 at 17:01
  • Yeah buddy, you did it! FYI in ES6 (javascript) a basic version of this looks like `let f=(v)=>Math.floor((Math.pow(1.618,v)-(-1.618))/Math.sqrt(5));` – Jacksonkr Sep 11 '17 at 17:55
2

Here's an approach which does not generate all numbers. When it comes to finding Fibonacci numbers fast there is a O(k log n) procedure where O(k) is the time it takes to multiply F(n) with F(n-1). It exploits the fact that F(n) is exactly the a[0][1] element of the matrix a which is the n-th power of the simple matrix [[1, 1], [1, 0]] (reference). So you can use exponentiation by squaring. Here is a sample python implementation:

def matrix_mult(a, b):
    return ((a[0][0]*b[0][0] + a[0][1]*b[1][0], 
             a[0][0]*b[0][1] + a[0][1]*b[1][1]),
            (a[1][0]*b[0][0] + a[1][1]*b[1][0], 
             a[1][0]*b[0][1] + a[1][1]*b[1][1]))


def matrix_pow(a, k):
    if k == 0:
        return ((1, 0), (0, 1))
    t = matrix_pow(a, k//2)
    t2 = matrix_mult(t, t)
    if k % 2 == 0:
        return t2
    return matrix_mult(t2, a)


def fib(n):
    a = ((1, 1), (1, 0))
    return matrix_pow(a, n)[0][1]


def get_first_k(n, k):
    return str(fib(n))[:k]

for n in range(10 ** 2, 10 ** 2 + 10):
    print(get_first_k(n, 3))

#output
#first 3 digits   actual number
354               #354224848179261915075
573               #573147844013817084101
927               #927372692193078999176
150               #1500520536206896083277
242               #2427893228399975082453
392               #3928413764606871165730
635               #6356306993006846248183
102               #10284720757613717413913
166               #16641027750620563662096
269               #26925748508234281076009

For n = 2 * 10 ** 5 it takes around 5s to calculate F_n which is reasonable given the nature of the problem.

Here's Java alternative

package stackoverflow;

import java.math.BigInteger;

public class Fibonacci {

    public static class Matrix {
        BigInteger[][] a;

        public Matrix(BigInteger n0, BigInteger n1, BigInteger n2, BigInteger n3) {
            a = new BigInteger[][]{{n0, n1}, {n2, n3}};
        }

        public BigInteger get(int i, int j) {
            return a[i][j];
        }

        @Override
        public String toString() {
            return String.format("%s %s\n%s %s", a[0][0], a[0][1], a[1][0], a[1][1]);
        }
    }

    Matrix matrixMult(Matrix a, Matrix b) {
        return new Matrix(a.get(0, 0).multiply(b.get(0, 0)).add(a.get(0, 1).multiply(b.get(1, 0))),
                          a.get(0, 0).multiply(b.get(0, 1)).add(a.get(0, 1).multiply(b.get(1, 1))),
                          a.get(1, 0).multiply(b.get(0, 0)).add(a.get(1, 1).multiply(b.get(1, 0))),
                          a.get(1, 0).multiply(b.get(0, 1)).add(a.get(1, 1).multiply(b.get(1, 1))));
    }

    Matrix power(Matrix a, int k) {
        if (k == 0)
            return new Matrix(new BigInteger("1"), new BigInteger("0"),
                              new BigInteger("0"), new BigInteger("1"));
        Matrix t = power(a, k / 2);
        Matrix t2 = matrixMult(t, t);
        if (k % 2 == 0)
            return t2;
        return matrixMult(t2, a);
    }

    BigInteger get(int n) {
        Matrix a = new Matrix(new BigInteger("1"), new BigInteger("1"),
                              new BigInteger("1"), new BigInteger("0"));
        return power(a, n).get(0, 1);
    }

    String getFirstK(int n, int k) {
        return get(n).toString().substring(0, k);
    }

    public static void main(String[] args) {
        Fibonacci f = new Fibonacci();

        System.out.println(f.getFirstK(200000, 10));
    }
}
sve
  • 4,336
  • 1
  • 19
  • 30
  • It is possible to generate the number.. but C, C++, Java does not provide any data type that can store 2*10^6 th Fibonacci number. If I can't store the number then how could I get the leftmost k digits? That is why I am asking for a solution that will calculate the leftmost k digits without generating the Fibonacci number. – Sourav Bhattacharjee Oct 04 '15 at 11:13
  • 1
    @souravbhattacharjee In Java you can easily can with `BigInteger` – sve Oct 04 '15 at 11:20
  • http://stackoverflow.com/questions/12088436/what-does-biginteger-having-no-limit-mean It say BigInteger can accommodate any length.. So hopefully I can accommodate 2*10^6 th Fibonacci number in big integer.. – Sourav Bhattacharjee Oct 04 '15 at 11:22
  • @souravbhattacharjee It sure will be possible. Do you want to see the Java code instead of the python one? – sve Oct 04 '15 at 11:28
  • It would be really helpful if you can provide. Thanks. – Sourav Bhattacharjee Oct 04 '15 at 11:30
  • 1
    @souravbhattacharjee Done! I hope it helps! – sve Oct 04 '15 at 12:03