I had originally coded the program wrongly. Instead of returning the Fibonacci numbers between a range (ie. startNumber 1, endNumber 20 should = only those numbers between 1
This is quite efficient, using O(log n) basic arithmetic operations.
def fib(n):
return pow(2 << n, n + 1, (4 << 2*n) - (2 << n) - 1) % (2 << n)
This one uses O(1) basic arithmetic operations, but the size of the intermediate results is large and so is not at all efficient.
def fib(n):
return (4 << n*(3+n)) // ((4 << 2*n) - (2 << n) - 1) & ((2 << n) - 1)
This one computes X^n in the polynomial ring Z[X] / (X^2 - X - 1) using exponentiation by squaring. The result of that calculation is the polynomial Fib(n)X + Fib(n-1), from which the nth Fibonacci number can be read.
Again, this uses O(log n) arithmetic operations and is very efficient.
def mul(a, b):
return a[0]*b[1]+a[1]*b[0]+a[0]*b[0], a[0]*b[0]+a[1]*b[1]
def fib(n):
x, r = (1, 0), (0, 1)
while n:
if n & 1: r = mul(r, x)
x = mul(x, x)
n >>= 1
return r[0]