Задача про n-ое число Фибоначчи

в 7:15, , рубрики: data science, fibonacci, integer, ml, sequences

Суть моего труда заключается в том, чтобы определить функцию для нахождения n-ого числа Фибоначчи с линейной сложностью поиска. Вот какие методы я попробовал:

Возможно получится по простым данным постоить полином большой степени, используя метод неопределённых коэффициентов и использовать его для подсчёта последующих значений последовательности.

# Тут я сделал через метод неопределённых коэффициентов, получилось примерно то что нужно,
# но из-за необходимости использования больших степеней, на полиноме возникают ненужные неровности.

import numpy as np
import matplotlib.pyplot as plt

n = 10 # Основной параметр

F1 = 0
F2 = 1
Y = [0, 1]
for _ in range(n - 2):
    A = F1 + F2
    F1 = F2
    F2 = A
    Y.append(A)

X = np.array([i for i in range(1, n + 1)])

print(X)
print(Y)
print(len(X) == len(Y))
R = []

for i in range(n):
  line = []
  for j in range(n):
    line.append(1*X[i] ** j)
  R.append(line)

R = np.array(R)
A = np.linalg.solve(R, Y)
linsp  = np.linspace(X.min(), X.max())
f = np.poly1d(np.flip(A))
fun = [f(x) for x in linsp]
plt.plot(linsp,fun);
plt.scatter(X, Y, color='r', alpha=0.5); # Рисуем исходные точки
#plt.plot(linsp,np.sin(2*linsp),'g--');
plt.grid(True)

[ 1 2 3 4 5 6 7 8 9 10]

[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

True

Задача про n-ое число Фибоначчи - 1

Всё немного съезжает на больших степенях, возможно это получится починить, используя метод через производные, чтобы вышел более плавный и "гладкий" полином:

[ 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]

[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229]

True

Первый замер числа под номером 30:

267394558.0

3524578

Задача про n-ое число Фибоначчи - 2

Чем плох первый метод? У полинома образуются ненужные углы и неровности в областях между точками, на основе которых он был построен.

Но логически подумав, нам ведь и не нужны эти нецелые промежуточные значения, ведь область определения нужной нам функции - целые числа.

Вывод: возможно стоит вернуться к первому методу и проверить его на больших числах:

# Метод неопределённых коэффициентов
import numpy as np
import matplotlib.pyplot as plt

n = 13 # Основной параметр

F1 = 0
F2 = 1
Y = [0, 1]
for _ in range(n - 2):
    A = F1 + F2
    F1 = F2
    F2 = A
    Y.append(A)

X = np.array([i for i in range(1, n + 1)])

print(X)
print(Y)
print(len(X) == len(Y))
R = []

for i in range(n):
  line = []
  for j in range(n):
    line.append(1*X[i] ** j)
  R.append(line)

R = np.array(R)
A = np.linalg.solve(R, Y)
linsp  = np.linspace(X.min(), X.max())
f = np.poly1d(np.flip(A))
fun = [f(x) for x in linsp]
plt.plot(linsp,fun);
plt.scatter(X, Y, color='r', alpha=0.5); # Рисуем исходные точки
#plt.plot(linsp,np.sin(2*linsp),'g--');
plt.grid(True)

# Проверяю:

print("Второй замер числа под номером 30:")
print(f(30).round(0))

# -5228112930.0

# Почему-то значение получилось отрицательным...

[ 1 2 3 4 5 6 7 8 9 10 11 12 13]

[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144]

True

Второй замер числа под номером 30:

-5228112930.0

Задача про n-ое число Фибоначчи - 3

Попробуем проанализировать график. Видно, что это экспонента.

Screenshot 2025-03-14 at 6.44.28 PM.png

общая формула для экспоненты

Подберём такие значения a и b чтобы все точки совпали:

import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit

n = 30  # Количество чисел Фибоначчи

# Генерация чисел Фибоначчи итеративным методом
fibonacci = [0, 1]
for i in range(2, n + 1):
    fibonacci.append(fibonacci[i - 1] + fibonacci[i - 2])

x_data = np.arange(0, n + 1)
y_data = np.array(fibonacci[:n+1])

# Определение экспоненциальной функции
def exponential_func(x, a, b):
    return a * np.exp(b * x)

# Подгонка параметров a и b с помощью curve_fit
popt, pcov = curve_fit(exponential_func, x_data, y_data, p0=[1, 0.1])  # p0 - начальные значения для a и b

a_opt, b_opt = popt
print("Оптимизированные параметры: a =", a_opt, "b =", b_opt)

# Генерация гладкой экспоненты для визуализации
x_smooth = np.linspace(x_data.min(), x_data.max(), 500)
y_smooth = exponential_func(x_smooth, a_opt, b_opt)

# Построение графика
plt.plot(x_smooth, y_smooth, color='blue', label='Экспонента (аппроксимация)')
plt.scatter(x_data, y_data, color='red', alpha=0.8, label='Точки Фибоначчи')

# Стилизация графика
plt.grid(True)
plt.xlabel('n')
plt.ylabel('F(n)')
plt.title('График экспоненты')
plt.legend()

# Отображение графика
plt.show()

Оптимизированные параметры: a = 0.44721359546613776 b = 0.4812118250621712

Задача про n-ое число Фибоначчи - 5

Автор: YanKhus

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js