简体   繁体   English

我的代码有什么问题? 第 N 个斐波那契数

[英]What is wrong with my code? Nth Fibonacci Number

  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];
    }
};

This is my code.这是我的代码。 It is giving output 0 for input 2, instead it should give 1.它为输入 2 提供输出 0,而不是它应该提供 1。

OK, we are talking about Fibonacci numbers and memoization.好的,我们正在谈论斐波那契数列和记忆。

The ultrafast and compact solution is to use compile time memoization.超快速和紧凑的解决方案是使用编译时记忆。 So, precalculate all possible values, that fit into a 64 unsigned bit, value during compile time.因此,在编译时预先计算所有可能的值,这些值适合 64 位无符号位值。

One important property of the Fibonacci series is that the values grow strongly exponential.斐波那契数列的一个重要属性是值呈指数级增长。 So, all existing build in integer data types will overflow rather quick.因此,所有现有的内置整数数据类型都会很快溢出。

With Binet's formula you can calculate that the 93rd Fibonacci number is the last that will fit in a 64bit unsigned value.使用比奈公式,您可以计算出第 93 个斐波那契数是最后一个适合 64 位无符号值的数。

And calculating 93 values during compilation is a really simple and fast task.在编译期间计算 93 个值是一项非常简单和快速的任务。

So, how to do?那么,怎么办?

We will first define the default approach for calculation a Fibonacci number as a constexpr function.我们首先将计算斐波那契数的默认方法定义为constexpr函数。 Iterative and non recursive.迭代和非递归。

// 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;
}

With that, Fibonacci numbers can easily be calculated at compile time.这样,可以在编译时轻松计算斐波那契数。 Then, we fill a std::array with all Fibonacci numbers.然后,我们用所有斐波那契数字填充std::array We use also a constexpr and make it a template with a variadic parameter pack.我们还使用constexpr并使其成为带有可变参数包的模板。

We use std::integer_sequence to create a Fibonacci number for indices 0,1,2,3,4,5, ....我们使用std::integer_sequence为索引 0,1,2,3,4,5, .... 创建一个斐波那契数。

That is straigtforward and not complicated:这很直接,并不复杂:

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

This function will be fed with an integer sequence 0,1,2,3,4,... and return a std::array<unsigned long long, ...> with the corresponding Fibonacci numbers.这个函数将输入一个整数序列 0,1,2,3,4,... 并返回一个std::array<unsigned long long, ...>与相应的斐波那契数列。

We know that we can store maximum 93 values.我们知道我们最多可以存储 93 个值。 And therefore we make a next function, that will call the above with the integer sequence 1,2,3,4,...,92,93, like so:因此我们创建了一个 next 函数,它将使用整数序列 1,2,3,4,...,92,93 调用上面的函数,如下所示:

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

And now, finally,而现在,终于,

constexpr auto FIB = generateArray();

will give us a compile-time std::array<unsigned long long, 93> with the name FIB containing all Fibonacci numbers.将给我们一个编译时std::array<unsigned long long, 93>名称为 FIB 的包含所有斐波那契数。 And if we need the i'th Fibonacci number, then we can simply write FIB[i] .如果我们需要第 i 个斐波那契数,那么我们可以简单地写FIB[i] There will be no calculation at runtime.运行时不会有计算。

I do not think that there is a faster or easier way to calculate the n'th Fibonacci number.我认为没有更快或更简单的方法来计算第 n 个斐波那契数。

Please see the complete program below:请参阅下面的完整程序:

#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;
}

Developed and tested with Microsoft Visual Studio Community 2019, Version 16.8.2.使用 Microsoft Visual Studio Community 2019 版本 16.8.2 进行开发和测试。

Additionally compiled and tested with clang11.0 and gcc10.2另外使用 clang11.0 和 gcc10.2 编译和测试

Language: C++17语言:C++17

You do not need to do lookup[n] = n if n <= 1 (that should also be the case you compare to).如果 n <= 1,您不需要执行 lookup[n] = n (这也应该是您比较的情况)。 For Fibonacci, you just need to return n for the first case.对于斐波那契,您只需要在第一种情况下返回 n。

I rewrote your code here我在这里重写了你的代码

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM