Что такое числа Фибоначчи и как их вычислить?

Ответ

Числа Фибоначчи — это классическая целочисленная последовательность, где каждое последующее число равно сумме двух предыдущих. Стандартное определение начинается с F₀ = 0 и F₁ = 1: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ...

Формула: Fₙ = Fₙ₋₁ + Fₙ₋₂, где n ≥ 2.

Сравнение подходов к вычислению на PHP:

  1. Наивная рекурсия (неэффективно, O(2ⁿ)):

    function fibRecursive(int $n): int {
        if ($n <= 1) return $n;
        return fibRecursive($n - 1) + fibRecursive($n - 2);
    }
    // Не подходит для n > 40 из-за экспоненциального времени.
  2. Итеративный метод (оптимально по памяти, O(n)):

    function fibIterative(int $n): int {
        if ($n <= 1) return $n;
        $prev = 0; // F₀
        $curr = 1; // F₁
        for ($i = 2; $i <= $n; $i++) {
            $next = $prev + $curr;
            $prev = $curr;
            $curr = $next;
        }
        return $curr;
    }
    echo fibIterative(10); // 55
  3. Рекурсия с мемоизацией (O(n)):

    function fibMemo(int $n, array &$memo = []): int {
        if ($n <= 1) return $n;
        if (!isset($memo[$n])) {
            $memo[$n] = fibMemo($n - 1, $memo) + fibMemo($n - 2, $memo);
        }
        return $memo[$n];
    }

Практическое замечание: Для вычисления очень больших чисел Фибоначчи (например, F₁₀₀₀) необходимо использовать библиотеки для работы с большими числами, такие как bcmath или gmp в PHP, так как значения быстро выходят за пределы стандартного целочисленного типа.

Ответ 18+ 🔞

Смотри, вот тебе история про числа Фибоначчи, которые все на собесах спрашивают, а потом нихуя не используют. Это такая последовательность, где каждое следующее число — это сумма двух предыдущих. Начинается с нуля и единицы: 0, 1, 1, 2, 3, 5, 8, 13... Ну ты понял, ёпта.

Формула проще некуда: Fₙ = Fₙ₋₁ + Fₙ₋₂. Вот и вся магия.

А теперь самое интересное — как это на PHP посчитать, чтобы не накрыться медным тазом по производительности.

Первый способ — наивная рекурсия. Это классический пример, как делать НЕ НАДО, если не хочешь, чтобы твой скрипт ебался как конь до второго пришествия. Сложность тут — овердохуища, O(2ⁿ).

function fibRecursive(int $n): int {
    if ($n <= 1) return $n;
    return fibRecursive($n - 1) + fibRecursive($n - 2);
}
// Для n > 40 уже пиздец как долго. Доверия к такому коду — ебать ноль.

Второй способ — итеративный. Вот это уже дело. Работает за O(n), памяти жрёт фиксированно, красота. Самый нормальный вариант в 95% случаев.

function fibIterative(int $n): int {
    if ($n <= 1) return $n;
    $prev = 0; // F₀
    $curr = 1; // F₁
    for ($i = 2; $i <= $n; $i++) {
        $next = $prev + $curr;
        $prev = $curr;
        $curr = $next;
    }
    return $curr;
}
echo fibIterative(10); // 55

Третий способ — рекурсия, но с мемоизацией. Тоже умный подход, если очень хочется рекурсию. Результаты запоминаем, чтобы не пересчитывать одно и то же по сто раз. Сложность тоже O(n).

function fibMemo(int $n, array &$memo = []): int {
    if ($n <= 1) return $n;
    if (!isset($memo[$n])) {
        $memo[$n] = fibMemo($n - 1, $memo) + fibMemo($n - 2, $memo);
    }
    return $memo[$n];
}

И главное практическое замечание, чувак. Если ты вдруг решишь посчитать, например, F₁₀₀₀, то сам от себя охуеешь, потому что число будет просто нереальных размеров. Стандартные целочисленные типы в PHP с таким пизда рулю. Тут надо использовать специальные библиотеки для больших чисел, типа bcmath или gmp, иначе получишь не то, что ожидал. Вот такая, блядь, хитрая жопа у этих, казалось бы, простых чисел.