Guest User

Untitled

a guest
Jul 24th, 2012
350
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.98 KB | None | 0 0
  1. import time, random
  2.  
  3. class MatrixFibonacci:
  4.     A = [[1, 1],
  5.          [1, 0]]
  6.  
  7.     def __init__(self):
  8.         self.__memo = {}
  9.  
  10.  
  11.     # умножение матриц
  12.     # ожидаются матрицы в виде списка список размером 2x2
  13.     def __multiply_matrices(self, M1, M2):
  14.         a11 = M1[0][0]*M2[0][0] + M1[0][1]*M2[1][0]
  15.         a12 = M1[0][0]*M2[0][1] + M1[0][1]*M2[1][1]
  16.         a21 = M1[1][0]*M2[0][0] + M1[1][1]*M2[1][0]
  17.         a22 = M1[1][0]*M2[0][1] + M1[1][1]*M2[1][1]
  18.         r = [[a11, a12], [a21, a22]]
  19.         return r
  20.  
  21.  
  22.     # возведение матрицы в степень
  23.     # ожидается p равная степени двойки
  24.     def __get_matrix_power(self, M, p):
  25.         if p == 1:
  26.             return M
  27.         if p in self.__memo:
  28.             return self.__memo[p]
  29.         K = self.__get_matrix_power(M, int(p/2))
  30.         R = self.__multiply_matrices(K, K)
  31.         self.__memo[p] = R
  32.         return R
  33.  
  34.  
  35.     # получение n-го числа Фибоначчи
  36.     # в качестве n ожидается неотрицательное целое число
  37.     def get_number(self, n):
  38.         if n == 0:
  39.             return 0
  40.         if n == 1:
  41.             return 1
  42.         # разложение переданной степени на степени, равные степени двойки
  43.         # т.е. 62 = 2^5 + 2^4 + 2^3 + 2^2 + 2^0 = 32 + 16 + 8 + 4 + 1
  44.         powers = [ int(pow(2, b)) for (b, d) in enumerate(reversed(bin(n-1)[2:])) if d == '1' ]
  45.         # тоже самое, но менее pythonic: http://pastebin.com/h8cKDkHX
  46.  
  47.         matrices = [ self.__get_matrix_power(MatrixFibonacci.A, p) for p in powers ]
  48.         while len(matrices) > 1:
  49.             M1 = matrices.pop()
  50.             M2 = matrices.pop()
  51.             R = self.__multiply_matrices(M1, M2)
  52.             matrices.append(R)
  53.         return matrices[0][0][0]
  54.  
  55.  
  56. class IterationFibonacci:
  57.     def __init__(self):
  58.         pass
  59.  
  60.     # получение n-го числа Фибоначчи
  61.     # в качестве n ожидается неотрицательное целое число
  62.     def get_number(self, n):
  63.         if n == 0:
  64.             return 0
  65.         a = 0
  66.         b = 1
  67.         c = 1
  68.         for i in range(n-1):
  69.             c = a + b
  70.             a = b
  71.             b = c
  72.         return c
  73.  
  74.  
  75. def benchmark():
  76.     random.seed()
  77.  
  78.     for around in range(10, 1010, 10):
  79.         ifib = IterationFibonacci()
  80.         mfib = MatrixFibonacci()
  81.         ti = 0
  82.         tm = 0
  83.         count = 10000
  84.         for _ in range(count):
  85.             n = random.randint(around-5, around+5)
  86.             t = time.time()
  87.             ifib.get_number(n)
  88.             t1 = time.time() - t
  89.             ti += t1
  90.  
  91.             t = time.time()
  92.             mfib.get_number(n)
  93.             t2 = time.time() - t
  94.             tm += t2
  95.  
  96.         print("{0}\t{1}\t{2}".format(around, ti, tm))
  97.  
  98.  
  99. benchmark()
Advertisement
Add Comment
Please, Sign In to add comment