【问题标题】:What is wrong with my code? Nth Fibonacci Number我的代码有什么问题?第 N 个斐波那契数
【发布时间】:2021-09-15 08:30:35
【问题描述】:
  public:
  
    long long int lookup[100]={-1};
    long long int nthFibonacci(long long int n){
        // code here
    
        if(lookup[n]==-1){
            if(n<=1) lookup[n]=n;
            else lookup[n]=nthFibonacci(n-1)+nthFibonacci(n-2);
        }
        return lookup[n];
    }
};

这是我的代码。它为输入 2 提供输出 0,而不是应该提供 1。

【问题讨论】:

  • long long int lookup[100]={-1}; 将第一个值初始化为 -1,其余的初始化为 0。
  • 有没有办法直接将数组的所有元素初始化为-1?
  • 不容易。 stackoverflow.com/questions/1065774/… 对于您的目的,0 和 -1 一样好,不是吗?你也可以使用std::vector&lt;long long&gt;(100, -1)
  • 知道了!谢谢

标签: c++ recursion dynamic dynamic-programming fibonacci


【解决方案1】:

好的,我们正在谈论斐波那契数字和记忆。

超快速和紧凑的解决方案是使用编译时记忆。因此,在编译期间预先计算所有可能的值,适合 64 无符号位的值。

斐波那契数列的一个重要特性是值呈指数级增长。因此,所有现有的整数数据类型构建都会很快溢出。

使用Binet's formula,您可以计算出第 93 个斐波那契数是最后一个适合 64 位无符号值的数。

在编译过程中计算 93 个值是一项非常简单快速的任务。

那么,怎么办?

我们首先将计算斐波那契数的默认方法定义为constexpr 函数。迭代和非递归。

// Constexpr function to calculate the nth Fibonacci number
constexpr unsigned long long getFibonacciNumber(size_t index) noexcept {
    // Initialize first two even numbers 
    unsigned long long f1{ 0 }, f2{ 1 };

    // calculating Fibonacci value 
    while (index--) {
        // get next value of Fibonacci sequence 
        unsigned long long f3 = f2 + f1;
        // Move to next number
        f1 = f2;
        f2 = f3;
    }
    return f2;
}

这样,斐波那契数可以在编译时轻松计算。然后,我们用所有斐波那契数填充std::array。我们还使用了constexpr,并使其成为带有可变参数包的模板。

我们使用std::integer_sequence 为索引 0、1、2、3、4、5、...创建一个斐波那契数。

这很简单,并不复杂:

template <size_t... ManyIndices>
constexpr auto generateArrayHelper(std::integer_sequence<size_t, ManyIndices...>) noexcept {
    return std::array<unsigned long long, sizeof...(ManyIndices)>{ { getFibonacciNumber(ManyIndices)... } };
};

这个函数将输入一个整数序列 0,1,2,3,4,... 并返回一个 std::array&lt;unsigned long long, ...&gt; 和相应的斐波那契数。

我们知道我们最多可以存储 93 个值。因此我们创建了一个 next 函数,它将使用整数序列 1,2,3,4,...,92,93 调用上述函数,如下所示:

constexpr auto generateArray() noexcept {
    return generateArrayHelper(std::make_integer_sequence<size_t, MaxIndexFor64BitValue>());
}

现在,终于,

constexpr auto FIB = generateArray();

将给我们一个编译时std::array&lt;unsigned long long, 93&gt;,名称为 FIB,包含所有斐波那契数。如果我们需要第 i 个斐波那契数,那么我们可以简单地写成FIB[i]。运行时不会进行计算。

我认为没有更快或更简单的方法来计算第 n 个斐波那契数。

请看下面的完整程序:

#include <iostream>
#include <array>
#include <utility>
// ----------------------------------------------------------------------
// All the following will be done during compile time

// Constexpr function to calculate the nth Fibonacci number
constexpr unsigned long long getFibonacciNumber(size_t index) {
    // Initialize first two even numbers 
    unsigned long long f1{ 0 }, f2{ 1 };

    // calculating Fibonacci value 
    while (index--) {
        // get next value of Fibonacci sequence 
        unsigned long long f3 = f2 + f1;
        // Move to next number
        f1 = f2;
        f2 = f3;
    }
    return f2;
}
// We will automatically build an array of Fibonacci numberscompile time
// Generate a std::array with n elements 
template <size_t... ManyIndices>
constexpr auto generateArrayHelper(std::integer_sequence<size_t, ManyIndices...>) noexcept {
    return std::array<unsigned long long, sizeof...(ManyIndices)>{ { getFibonacciNumber(ManyIndices)... } };
};

// Max index for Fibonaccis that for in an 64bit unsigned value (Binets formula)
constexpr size_t MaxIndexFor64BitValue = 93;

// Generate the required number of elements
constexpr auto generateArray()noexcept {
    return generateArrayHelper(std::make_integer_sequence<size_t, MaxIndexFor64BitValue>());
}

// This is an constexpr array of all Fibonacci numbers
constexpr auto FIB = generateArray();
// ----------------------------------------------------------------------

// Test
int main() {

    // Print all possible Fibonacci numbers
    for (size_t i{}; i < MaxIndexFor64BitValue; ++i)

        std::cout << i << "\t--> " << FIB[i] << '\n';

    return 0;
}

使用 Microsoft Visual Studio Community 2019 版本 16.8.2 开发和测试。

使用 clang11.0 和 gcc10.2 额外编译和测试

语言:C++17

【讨论】:

    【解决方案2】:

    如果n

    我在这里重写了你的代码

     long long int nthFibonacci(long long int n)
        {
        if (n <= 1)
           return n;
        return nthFibonacci(n-1) + nthFibonacci(n-2);
        }
    

    【讨论】:

    • 您似乎错过了预期实施的重点。当已经计算了先前的嵌套值时,它旨在递归。如果执行两个相同的值,结果应该是立即的,根本不需要递归。
    • 感谢您的回答,但我正在尝试使用记忆化(使用查找表来存储已计算的值)
    猜你喜欢
    • 1970-01-01
    • 2022-12-10
    • 1970-01-01
    • 1970-01-01
    • 2018-09-09
    • 2015-12-19
    • 1970-01-01
    • 2011-09-30
    • 1970-01-01
    相关资源
    最近更新 更多