簡體   English   中英

C++ 斐波那契數生成器不工作。 為什么?

[英]C++ Fibonacci number generator not working. Why?

我只是想知道為什么這種獲取斐波那契數的方法不起作用謝謝。

#include <iostream>
#include <cctype>
#include <cmath>
using namespace std;

int fibonacci()
{
    cout << "enter sequence num: " << endl;
    int num;
    cin >> num;
    int list[num] = {0, 1};
    int x;

    if (num == 1)
    {
        cout << "the " << num << " fibo num is " << 0 << endl;
    }
    else if (num == 2)
    {
        cout << "the " << num << " fibo num is " << 1 << endl;
    }
    else
    {
        for (int y = 0; y < num - 2; y++)
        {
            // get new fibo value

            x = list[y] + list[y + 1];
            for (int z = 2; z < num; z++)
            {
                // will append new value to the list

                list[z] = x;
            }
        }
        cout << "the " << num << " fibo num is " << list[-1] << endl;
        // get the last value which is the fibo value
    }
}

int main()
{
    fibonacci();

    return 0;
}

對於初學者可變長度 arrays 那樣

cin>>num;
int list[num] = {0,1};

不是標准的 C++ 功能。 事實上,計算斐波那契數不需要使用數組。

而且這個聲明

int list[num] = {0, 1};

如果變量num的輸入值等於1 ,則無效。 即使在有條件地支持可變長度 arrays 的 C 中,您也不能在其聲明中初始化可變長度數組。

盡管如此,在這份聲明中

cout<<"the "<<num<<" fibo num is "<<list[-1]<<endl;

表達式list[-1]訪問數組外部的 memory 調用未定義的行為。

看來你的意思

cout<<"the "<<num<<" fibo num is "<<list[num-1]<<endl;

我將通過以下方式定義 function,如下面的演示程序所示。

#include <iostream>
#include <utility>

unsigned long long Fibonacci( unsigned int n )
{
    unsigned long long first = 0, second = 1;

    for ( unsigned i = 0; i < n; i++ )
    {
        first = std::exchange( second, first + second );
    }

    return first;
}


int main()
{
    const unsigned int N = 10;

    for ( unsigned int i = 0; i < N; i++ )
    {
        std::cout << i << ": " << Fibonacci( i ) << '\n';
    }
}

程序 output 是

0: 0
1: 1
2: 1
3: 2
4: 3
5: 5
6: 8
7: 13
8: 21
9: 34

來自莫斯科的 Vlad 已經展示了您代碼中的問題。

我想補充一點,根本不需要在運行時計算斐波那契數。 編譯器將成為您的朋友。

超快速和緊湊的解決方案是使用編譯時間計算。 因此,在編譯期間預先計算適合 64 位無符號位的所有可能值。

斐波那契數列的一個重要特性是值呈指數級增長。 因此,integer 數據類型中的所有現有構建將很快溢出。

使用比內特的公式,您可以計算出第 93 個斐波那契數是最后一個適合 64 位無符號值的數。

在編譯期間計算 93 個值是一項非常簡單且快速的任務。

那么,該怎么做呢?

我們首先將計算斐波那契數的默認方法定義為constexpr function。 迭代和非遞歸。

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

這個 function 將被輸入一個 integer 序列 0,1,2,3,4,... 並返回一個std::array<unsigned long long, ...>與相應的斐波那契數。

我們知道我們最多可以存儲 93 個值。 因此我們制作了下一個 function,它將使用 integer 序列 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<unsigned long long, 93>名稱 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

這里有一些不一致的索引。 如果 num = 1,則斐波那契數為 0,如果 num=2,則斐波那契數為 1……但這與聲明 int list[num] = {0,1} 不太匹配,因為索引以 0 開頭.

我重寫了代碼,使第一個數字的索引為 1(list[1]=0 和 list[2]=1)

append 不需要嵌套 for 循環來獲取數組末尾的新總和。 只需一個簡單的 for 循環即可。

I have modified your code below, see below.

#include <iostream>
#include <cctype>
#include <cmath>
using namespace std;

int fibonacci(){
   cout<<"enter sequence num: "<<endl;
   int num;
   cin>>num;
   int list[num];
   list[1] = 0;
   list[2] = 1;
   int x;

   if(num==1){
       cout<<"the "<<num<<" fibo num is "<<0<<endl;
   }else if(num==2){
       cout<<"the "<<num<<" fibo num is "<<1<<endl;
   }else{
       for(int y=3;y<=num;y++){ 
              list[y]=list[y-1]+list[y-2];
       }
   }
   cout<<"the "<<num<<" fibo num is "<<list[num]<<endl; 
   
}

int main()
{
   fibonacci();
   return 0;
} 

希望這可以幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM