-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathfibonacci.py
130 lines (109 loc) · 3.41 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
128
129
130
# 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 functools
import math
import time
from decimal import Decimal, getcontext
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)