forked from TheAlgorithms/Python
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfibonacci.py
127 lines (106 loc) · 3.5 KB
/
fibonacci.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# fibonacci.py
"""
1. Calculates the iterative fibonacci sequence
2. Calculates the fibonacci sequence with a formula
an = [ Phin - (phi)n ]/Sqrt[5]
reference-->Su, Francis E., et al. "Fibonacci Number Formula." Math Fun Facts. <http://www.math.hmc.edu/funfacts>
"""
import math
import functools
import time
from decimal import getcontext, Decimal
getcontext().prec = 100
def timer_decorator(func):
@functools.wraps(func)
def timer_wrapper(*args, **kwargs):
start = time.time()
func(*args, **kwargs)
end = time.time()
if int(end - start) > 0:
print(f"Run time for {func.__name__}: {(end - start):0.2f}s")
else:
print(f"Run time for {func.__name__}: {(end - start)*1000:0.2f}ms")
return func(*args, **kwargs)
return timer_wrapper
# define Python user-defined exceptions
class Error(Exception):
"""Base class for other exceptions"""
class ValueTooLargeError(Error):
"""Raised when the input value is too large"""
class ValueTooSmallError(Error):
"""Raised when the input value is not greater than one"""
class ValueLessThanZero(Error):
"""Raised when the input value is less than zero"""
def _check_number_input(n, min_thresh, max_thresh=None):
"""
:param n: single integer
:type n: int
:param min_thresh: min threshold, single integer
:type min_thresh: int
:param max_thresh: max threshold, single integer
:type max_thresh: int
:return: boolean
"""
try:
if n >= min_thresh and max_thresh is None:
return True
elif min_thresh <= n <= max_thresh:
return True
elif n < 0:
raise ValueLessThanZero
elif n < min_thresh:
raise ValueTooSmallError
elif n > max_thresh:
raise ValueTooLargeError
except ValueLessThanZero:
print("Incorrect Input: number must not be less than 0")
except ValueTooSmallError:
print(
f"Incorrect Input: input number must be > {min_thresh} for the recursive calculation"
)
except ValueTooLargeError:
print(
f"Incorrect Input: input number must be < {max_thresh} for the recursive calculation"
)
return False
@timer_decorator
def fib_iterative(n):
"""
:param n: calculate Fibonacci to the nth integer
:type n:int
:return: Fibonacci sequence as a list
"""
n = int(n)
if _check_number_input(n, 2):
seq_out = [0, 1]
a, b = 0, 1
for _ in range(n - len(seq_out)):
a, b = b, a + b
seq_out.append(b)
return seq_out
@timer_decorator
def fib_formula(n):
"""
:param n: calculate Fibonacci to the nth integer
:type n:int
:return: Fibonacci sequence as a list
"""
seq_out = [0, 1]
n = int(n)
if _check_number_input(n, 2, 1000000):
sqrt = Decimal(math.sqrt(5))
phi_1 = Decimal(1 + sqrt) / Decimal(2)
phi_2 = Decimal(1 - sqrt) / Decimal(2)
for i in range(2, n):
temp_out = ((phi_1 ** Decimal(i)) - (phi_2 ** Decimal(i))) * (
Decimal(sqrt) ** Decimal(-1)
)
seq_out.append(int(temp_out))
return seq_out
if __name__ == "__main__":
num = 20
# print(f'{fib_recursive(num)}\n')
# print(f'{fib_iterative(num)}\n')
# print(f'{fib_formula(num)}\n')
fib_iterative(num)
fib_formula(num)