I wanted to use
[[1, 1], [1, 0]]
return (numpy.matrix("1 1; 1 0")**n).item(1)
# Gives -1581614984
The reason you see negative values appearing is because NumPy has defaulted to using the
np.int32 dtype for your matrix.
The maximum positive integer this dtype can represent is 231-1 which is 2147483647. Unfortunately, this is less the 47th Fibonacci number, 2971215073. The resulting overflow is causing the negative number to appear:
>>> np.int32(2971215073) -1323752223
Using a bigger integer type (like
np.int64) would fix this, but only temporarily: you'd still run into problems if you kept on asking for larger and larger Fibonacci numbers.
The only sure fix is to use an unlimited-size integer type, such as Python's
int type. To do this, modify your matrix to be of
def fib_2(n): return (np.matrix("1 1; 1 0", dtype=np.object)**n).item(1)
np.object type allows a matrix or array to hold any mix of native Python types. Essentially, instead of holding machine types, the matrix is now behaving like a Python list and simply consists of pointers to integer objects in memory. Python integers will be used in the calculation of the Fibonacci numbers now and overflow is not an issue.
This flexibility comes at the cost of decreased performance: NumPy's speed originates from direct storage of machine integer/float types.