65.9K
CodeProject 正在变化。 阅读更多。
Home

计算斐波那契数的算法方法

starIconstarIconstarIconstarIconstarIcon

5.00/5 (3投票s)

2014 年 8 月 24 日

CPOL

3分钟阅读

viewsIcon

18493

downloadIcon

62

一些用于计算斐波那契数的算法建议,涉及迭代、递归和函数式编程范例

解释

又一个斐波那契数列算法?
是的,这是我正在撰写的一系列数学文章中的第二篇,斐波那契数列不可或缺。
但是,我将采用不同的方法来计算它:

  • 如何计算整个数列;
  • 如何通过其位置获取特定元素;
  • 如何实现迭代、递归和函数式编程范例。

引言

请注意下面的数值序列

1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89,144, 233, ...

请注意,除了前两个项之外,所有其他项都可以使用前两个项的总和来计算,根据以下公式,其中 M 是一维数组

公式 #1

M(1) = 1;
M(2) = 1;
M(n) = M(n-1) + M(n-2),对于 n > 2。

可以用递归方式描述这个公式

公式 #2

F(1) = 1;
F(2) = 1;
F(n) = F(n-1) + F(n-2),对于 n > 2。

还有比奈公式,允许通过它在序列中的位置来计算元素

公式 #3

The Binet's formula
比奈公式,对于 n >= 0。


但最终,为什么这些数字如此重要? 显然,它没有什么实际用途。

下面,让我们回答这个问题...

一点历史

Fibonacci莱昂纳多·斐波那契(Leonardo of Pisa),也被称为斐波那契(Bonaccio之子),生活在十二世纪的意大利。
作为一位伟大商人的儿子,他一生大部分时间都在旅行和与阿拉伯人一起学习数学,这导致出版了一些关于代数和算术的书籍,其中我们特别感兴趣的是题为“Liber Abbaci”的作品,其中包含著名的兔子问题
 

"如果每个月每对兔子都会产下一对新的兔子,而新生兔子从第二个月开始就可以繁殖,那么一年内将会产生多少对兔子?"

莱昂纳多根据下表进行了计算

Fibonacci's Table

继续推论,表明我们在 12 个月后将有 144 对兔子。

后来,其他数学家研究了这个序列,发现它存在于其他自然现象中。 其中,我们重点介绍以下使用它的科学领域:

  • 光线的反射;
  • 在某些植物和动物的研究中;
  • 在几何学中,计算黄金分割

公式 公式 #3 中描述的比奈公式最初由莱昂哈德·欧拉于 1765 年发表,但一直被遗忘,直到 1843 年被法国数学家雅克·比奈重新发现。

作为对斐波那契一生的最终观察,我们可以说,他是欧洲数学家中最公开代数的人,极大地促进了代数的普及……

背景

为了测试这里提出的算法,我建议使用以下工具

C / C++ 语言
Pascal 语言
Haskell 语言

使用代码

毫无疑问,处理斐波那契数的最简单和最快的方法是通过比奈公式,特别是当我们只需要一个元素时。
要获得整个序列,最常用的方法是迭代法,因为它只执行求和运算。

现在让我们考虑一下C、Pascal 和 Haskell 中迭代、递归和函数式方法的算法实现...

用于计算整个序列的算法

迭代方法(公式 #1)

// Purpose: Computing the fibonacci numbers in a Iterative way
// Language: C
// Author: Jose Cintra (jose.cintra@html-apps.info)
  
main() { 

  unsigned long int n, current = 1, last = 0, penult = 1, count; 

  printf("The Fibonacci Numbers\n");
  printf("\nEnter the number of elements: ");
  scanf("%d",&n);

  for (count = 1; count <= n; count++) {
    current = last + penult;
    penult = last;
    last = current;
    printf("%d  ",current);
  }
      
}

关注点
请注意,三个主要变量中的值已初始化。 因此,可以计算所有元素,而无需速度较慢的条件结构。

通过其位置获取特定元素的算法

递归方法(公式 #2)

{
Purpose: Get a Fibonacci number in a recursive way 
Linguagem: Pascal
Author: Jose Cintra (jose.cintra@html-apps.info)
}

var
index : integer;

function Fibo(index : integer) : integer;
begin
if index < 3 then
  Fibo := 1
else
  Fibo := Fibo(index - 1) + Fibo(index - 2);
end;

begin
writeln('The Fibonacci Numbers');
write('Enter the element''s position: ');
readln(index);
writeln('The element in this position is: ',Fibo(index));
end.


函数式方法(公式 #1)

Purpose: Get a Fibonacci number in a functional way 
Linguagem: Haskell
Author: Jose Cintra (jose.cintra@html-apps.info)

fibo :: Int -> Int
fibolist :: [Int]
fibolist = 0 : 1 : zipWith (+) fibolist (tail fibolist)
fibo n = fibolist!!n


比奈公式(公式 #3)

// Purpose: Get a Fibonacci number through the Binet's Formula 
// Linguagem: C++
// Author: Jose Cintra (jose.cintra@html-apps.info)

#include <iostream>
#include <stdlib.h>
#include <math.h>
using namespace std;
int main() {
  int i,f;
  cout << "The Fibonacci Numbers\n";
  cout << "Enter the element's position: "; 
  cin >> i;
  f = round((pow((1+sqrt(5))/2,i)-pow((1-sqrt(5))/2,i))/ sqrt(5));
  cout << "The element in this position is: " << f;
}

结论

就是这样了!

与往常一样,当我们使用传统语言实现算法时,需要考虑的一点是,斐波那契的值往往会快速增长,导致结果溢出。 解决方案是采用支持任意精度数的库或语言。 函数式语言通常没有这种缺陷。

希望这有帮助。 欢迎提出问题和评论。

在此处下载源代码

再见..

参考文献

http://en.wikipedia.org/wiki/Fibonacci

http://en.wikipedia.org/wiki/Fibonacci_number

© . All rights reserved.