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