cubbi.com: fibonacci numbers in c++
C++
Date: 1986 (Standards: ISO/IEC 14882:1998, ISO/IEC 14882:2003)
Type: Object-oriented language with excessive features
Usage: Wide variety of software. This is the language I use at work.

ALGORITHM 1A: NAIVE BINARY RECURSION
// This program calculates the nth fibonacci number
// using alrogirhtm 1A: naive binary recursion
//
// compiled: g++ -std=c++0x -Wall -Wextra -pedantic -O2 -march=native -o f1a f1a.cc
// executed: ./f1a n
//
#include <iostream>
#include <stdexcept>
#include <vector>

// Naive binary recursion: F(n) = F(n-1) + F(n-2)
long fib(int n) {
    return n<2 ? n : fib(n-1) + fib(n-2);
}
// Function f(n) handles the negative arguments: F(-n) = F(n)*(-1)^(n+1) 
long f(int n) {
    if(n<0)
       return n%2 ? fib(-n) : -fib(-n);
    else
       return fib(n);
}
// Function f_print prints out n'th Fibonacci number
void fib_print(int n) {
    std::cout << n << "th Fibonacci number is " << f(n) << '\n';
}
// entry point:
// convert the first argument to a number and calls fib_print
// if argument did not exist or wasn't a number, show usage information
int main(int argc, char** argv) {
    std::vector<std::string> args(argv, argv+argc);
    try {
        fib_print(stoi(args.at(1)));
    } catch (std::exception& ) {
        std::cout << "Usage: " << args[0] << " <n>\n";
    }
}

ALGORITHM 1B: CACHED BINARY RECURSION / MEMOIZATION
// This program calculates the nth fibonacci number
// using algorithm 1B: cached binary recursion
//
// compile: g++ -std=c++0x -O2 -o f1b f1b.cc -lgmpxx -lgmp
// executed: ./f1b n

#include <iostream>
#include <stdexcept>
#include <unordered_map>
#include <gmpxx.h>
#include <vector>
typedef std::unordered_map<int, mpz_class> memo;

// Naive binary recursion: F(n) = F(n-1) + F(n-2) with memoization
// First checks if the answer is known, reports it if it is known
// then recurses twice, saves the new answer, and returns it.
mpz_class frec(int n, memo& m) {
   memo::iterator i = m.find(n);
   if(i!=m.end()) return i->second;
   return n<2 ? n : m[n] = frec(n-1, m) + frec(n-2, m);
}

// Function fib initializes the memoization data structure and calls frec
mpz_class fib(int n) {
    memo m;
    return frec(n, m);
}

// Function f(n) handles the negative arguments: F(-n) = F(n)*(-1)^(n+1)
mpz_class f(int n) {
    if(n<0)
        return n%2 ? fib(-n) : 0-fib(-n);
    else
        return fib(n);
}

// Function fib_print prints out n'th Fibonacci number
void fib_print(int n) {
    std::cout << n << "th Fibonacci number is "
              << f(n).get_str(10) << '\n';
}
// entry point:
// convert the first argument to a number and calls fib_print
// if argument did not exist or wasn't a number, show usage information
int main(int argc, char** argv) {
    std::vector<std::string> args(argv, argv+argc);
    try {
        fib_print(stoi(args.at(1)));
    } catch (std::exception& ) {
        std::cout << "Usage: " << args[0] << " <n>\n";
    }
}

ALGORITHM 2A: CACHED LINEAR RECURSION / RANDOM-ACCESS CONTAINER
// This program calculates the nth fibonacci number
// using algorithm 2A: cached linear iteration with random-access container
//
// compile: g++ -std=c++0x -O2 -o f2a f2a.cc -lgmpxx
// executed: ./f2a n
//
#include <iostream>
#include <algorithm>
#include <sstream>
#include <gmpxx.h>
#include <deque>

// Function f1b creates a deque containing the numbers {0, 1}, 
// and recursively appends the sum of the last two numbers
mpz_class flrec(std::deque<mpz_class>& fl, int n) { fl.push_front(fl[0] + fl[1]); return n<1 ? fl.front() : flrec(fl, n-1); } mpz_class fib(int n) { std::deque<mpz_class> fl = {1, 0}; return n<2 ? n : flrec(fl, n-2); } // Function f(n) handles the negative arguments: F(-n) = F(n)*(-1)^(n+1) mpz_class f(int n) { if(n<0) return n%2 ? fib(-n) : 0-fib(-n); else return fib(n); } // Function fib_print prints out n'th Fibonacci number void fib_print(int n) { std::cout << n << "th Fibonacci number is " << f(n).get_str(10) << '\n'; } // entry point // check the number of command line arguments // convert the first argument to a number and calls fib_print // if argument did not exist or wasn't a number, show usage information int main(int argc, char** argv) { std::vector<std::string> args(argv, argv+argc); try { fib_print(stoi(args.at(1))); } catch (std::exception& ) { std::cout << "Usage: " << args[0] << " <n>\n"; } }

ALGORITHM 2B: LINEAR RECURSION WITH ACCUMULATORS
// This program calculates the nth fibonacci number
// using algorithm 2B: linear recursion with accumulator
//
// compile: g++ -std=c++0x -O2 -o f2b f2b.cc -lgmpxx -lgmp
// executed: ./f2b n
//
#include <iostream>
#include <sstream>
#include <gmpxx.h>
#include <vector>

// Function fib(x) calculates F(n) by linear recursion
// keeping two accumulators, F(n-1) and F(n-2)
mpz_class fib(int x, mpz_class x1 = 0, mpz_class x2 = 1) {
    return x<1 ? x1 : fib(x-1, x2+x1, x1);
}

// Function f(n) handles the negative arguments: F(-n) = F(n)*(-1)^(n+1)
mpz_class f(int n) {
    if(n<0)
        return n%2 ? fib(-n) : 0-fib(-n);
    else
        return fib(n);
}

// Function fib_print prints out n'th Fibonacci number
void fib_print(int n) {
    std::cout << n << "th Fibonacci number is "
              << f(n).get_str(10) << '\n';
}
// entry point
// check the number of command line arguments
// convert the first argument to a number and calls fib_print
// if argument did not exist or wasn't a number, show usage information
int main(int argc, char** argv) {
    std::vector<std::string> args(argv, argv+argc);
    try {
        fib_print(stoi(args.at(1)));
    } catch (std::exception& ) {
        std::cout << "Usage: " << args[0] << " <n>\n";
    }
}

ALGORITHM 2C: IMPERATIVE LOOP WITH MUTABLE VARIABLES
// This program calculates the nth fibonacci number
// using algorithm 2C: imperative loop with mutable variables
//
// compile: g++ -std=c++0x -O2 -o f2c f2c.cc -lgmpxx
// executed: ./f2c n
//
#include <iostream>
#include <algorithm>
#include <sstream>
#include <gmpxx.h>
#include <vector>
#include <numeric>
#include <functional>

// Traditional iterative loop would be something like
// mpz_class fib(int x) {
//     mpz_class x1=0;
//     mpz_class x2=1;
//     for(int i=1; i<=(x<0?-x:x); ++i)
//         std::swap(x1+=x2,x2);
//     return (x<0 && x%2==0) ? 0-x1 : x1;
// }
//  but C++ offers ways to abstract over loops

mpz_class fib(int x) {
    if(x==0) return x;
    std::vector<mpz_class> v(x, 1);
    adjacent_difference(v.begin(), v.end()-1, v.begin()+1, std::plus<mpz_class>());
    return v[x-1];
}

// Function f(n) handles the negative arguments: F(-n) = F(n)*(-1)^(n+1)
mpz_class f(int n) {
    if(n<0)
        return n%2 ? fib(-n) : 0-fib(-n);
    else
        return fib(n);
}

// Function fib_print prints out n'th Fibonacci number
void fib_print(int n) {
    std::cout << n << "th Fibonacci number is "
              << fib(n).get_str(10) << '\n';
}
// entry point
// check the number of command line arguments
// convert the first argument to a number and calls fib_print
// if argument did not exist or wasn't a number, show usage information
int main(int argc, char** argv) {
    std::vector<std::string> args(argv, argv+argc);
    try {
        fib_print(stoi(args.at(1)));
    } catch (std::exception& ) {
        std::cout << "Usage: " << args[0] << " <n>\n";
    }
}

ALGORITHM 3A: MATRIX MULTIPLICATION
// This program calculates the nth fibonacci number
// using algorithm 3A: matrix multiplication
//
// compile: g++ -std=c++0x -O2 -o f3a f3a.cc -lgmpxx -lgmp
// executed: ./f3a n

#include <iostream>
#include <sstream>
#include <gmpxx.h>
#include <vector>
#include <boost/numeric/ublas/matrix.hpp> 
typedef boost::numeric::ublas::matrix<mpz_class> matrix;
typedef boost::numeric::ublas::identity_matrix<mpz_class> identity_matrix;

// This overload of operator ^ raises a martix to integer power
// using repeated squaring.
matrix operator^(const matrix& a, int n) {
    if(n<=0) return identity_matrix(a.size1(), a.size2());
    matrix b(prod(a,a));
    return n&1 ? prod(a,b^n>>1) : b^n>>1;
}

// Function fib prepares the (1,1)(1,0) matrix, raises it
// to the x-1'st power, and returns the top left corner of the matrix
mpz_class fib(int x) {
    matrix A(2,2);
    A(0,0)=A(0,1)=A(1,0)=1; A(1,1)=0;
    return x==0 ? 0 : (A^(x-1))(0,0);
}

// Function f(n) handles the negative arguments: F(-n) = F(n)*(-1)^(n+1)
mpz_class f(int n) {
    if(n<0)
        return n%2 ? fib(-n) : 0-fib(-n);
    else
        return fib(n);
}

// Function fib_print prints out n'th Fibonacci number
void fib_print(int n) {
    std::cout << n << "th Fibonacci number is "
              << f(n).get_str(10) << '\n';
}
// entry point
// check the number of command line arguments
// convert the first argument to a number and calls fib_print
// if argument did not exist or wasn't a number, show usage information
int main(int argc, char** argv) {
    std::vector<std::string> args(argv, argv+argc);
    try {
        fib_print(stoi(args.at(1)));
    } catch (std::exception& ) {
        std::cout << "Usage: " << args[0] << " <n>\n";
    }
}

ALGORITHM 3B: FAST RECURSION
// This program calculates the nth fibonacci number
// using algorithm 3B: fast recursion
//
// compile: g++ -std=c++0x -O2 -o f3b f3b.cc -lgmpxx -lgmp
// executed: ./f3b n

#include <iostream>
#include <sstream>
#include <vector>
#include <gmpxx.h>

// calculate a pair of fibonacci numbers according to
// the recurrent relationship: 
// F(2n-1) = F(n-1)^2 + F(n)^2
// F(2n) = (2F(n-1) + F(n))F(n)
//
// in this function, f1 = F(n-1), f2 = F(n), f3 = F(n+1)
std::pair<mpz_class, mpz_class> fib_rec(int n) {
    if(n<=0) return {0,0};
    if(n==1) return {0,1};
    auto k = fib_rec(n/2);
    mpz_class f1 = k.first;
    mpz_class f2 = k.second;
    mpz_class f3 = f1+f2;
    if (n%2) return { (f1+f3)*f2, f3*f3+f2*f2 };
    else     return { f1*f1+f2*f2, (f1+f3)*f2 };
}

// Function fib calls fib_rec and returns the second of the two
// values returned. 
mpz_class fib(int x) {
    return fib_rec(x).second;
}

// Function f(n) handles the negative arguments: F(-n) = F(n)*(-1)^(n+1)
mpz_class f(int n) {
    if(n<0)
        return n%2 ? fib(-n) : 0-fib(-n);
    else
        return fib(n);
}

// Function fib_print prints out n'th Fibonacci number
void fib_print(int n) {
    std::cout << n << "th Fibonacci number is "
              << f(n).get_str(10) << '\n';
}
// entry point
// check the number of command line arguments
// convert the first argument to a number and calls fib_print
// if argument did not exist or wasn't a number, show usage information
int main(int argc, char** argv) {
    std::vector<std::string> args(argv, argv+argc);
    try {
        fib_print(stoi(args.at(1)));
    } catch (std::exception& ) {
        std::cout << "Usage: " << args[0] << " <n>\n";
    }
}

ALGORITHM 3C: BINET'S FORMULA WITH ROUNDING
// This program calculates the nth fibonacci number
// using algorithm 3C: Binet's formula with rounding
//
// compile: g++ -std=c++0x -O2 -o f3c f3c.cc -lgmpxx -lgmp
// executed: ./f3c n

#include <iostream>
#include <sstream>
#include <vector>
#include <gmpxx.h>

// This overload of operator ^ raises a number to integer power
// using repeated squaring.
mpf_class operator^(const mpf_class& a, int n) {
   if(n<=0) return 1;
   mpf_class b = a*a;
   b = b^n>>1;
   return n&1 ? a*b : b;
}

// This function calculates the nth fibonacci number
// as floor( phi^n/sqrt(5) + 1/2), where phi = (1+sqrt(5.0))/2;
mpz_class fib(int x) {
    mpf_class five(5, 0.7*x); // 5.0 with precision of x*log_2(phi) = 0.694*x
    mpf_class sqrt5 = sqrt(five);
    mpf_class phi = (1+sqrt5)/2;
    return floor((phi^x)/sqrt5 + 0.5);
}

// Function f(n) handles the negative arguments: F(-n) = F(n)*(-1)^(n+1)
mpz_class f(int n) {
    if(n<0)
        return n%2 ? fib(-n) : 0-fib(-n);
    else
        return fib(n);
}

// Function fib_print prints out n'th Fibonacci number
void fib_print(int n) {
    std::cout << n << "th Fibonacci number is "
              << f(n).get_str(10) << '\n';
}
// entry point
// check the number of command line arguments
// convert the first argument to a number and calls fib_print
// if argument did not exist or wasn't a number, show usage information
int main(int argc, char** argv) {
    std::vector<std::string> args(argv, argv+argc);
    try {
        fib_print(stoi(args.at(1)));
    } catch (std::exception& ) {
        std::cout << "Usage: " << args[0] << " <n>\n";
    }
}