一个斐波拉契数列的c++程序的思考

课本本来的程序

#include<iostream>
using namespace std;
int main()
{
  unsigned int a1=0,a2=1,limit=4294967295;
  while(a1<=limit/2)
  {
    cout<<a2<<" ";
    int sun=a1+a2;

    a1=a2;
    a2=sun;
   }
  return 0;
}

运行结果为:1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368 75025 121393 196418 317811 514229 832040 1346269 2178309 3524578 5702887 9227465 14930352 24157817 39088169 63245986 102334155 165580141 267914296 433494437 701408733 1134903170 1836311903 2971215073

课本上说斐波拉契数列不断延长时后两项的比值越来越接近黄金分割点。

这里有几点很重要:原先认为while的限定条件a2也可以胜任,但是由于a2最后一步有可能超出unsigned int的限定范围出现一些别的数到十循环继续下去,造成最后的错误。所以最好是a1限定。

思考:(以下为我自己考虑的过程,为防再犯这样的错误,警示下)

自己能否用上面的程序顺便求出最后两项的比值看看是不是真的近似黄金分割点,于是步骤如下:

#include<iostream>
using namespace std;
int main()
{
  unsigned int a1=0,a2=1,limit=4294967295;
  while(a1<=limit/2)
  {
    cout<<a2<<" ";
    int sun=a1+a2;

    a1=a2;
    a2=sun;
   }

  cout<<a1/a2<<endl;
  return 0;
}

本以为就这么简单就搞定了,谁知道结果为 5。这是怎么回事呢:原来当执行到倒数第二次的时候 a1=1836311903、a2=2971215073(还没有输出到桌面上)了,这时候由于a1还满足a1<=limit/2=2147483647,所以还要执行一次,这时候a2输出到桌面,而再执行sun=a1+a2的是sun超过范围溢出了,即a2为溢出后的值,而此时a1的值已经变为2971215073,所以这样直接相除已经与我们所想象的操作差了十万八千里了。

②既然这样,我就在想怎么能消除溢出的干扰,最后相除的又是数列的最后两个值呢?于是乎又出现了下面的想法:

#include<iostream>
using namespace std;
int main()
{
  unsigned int a1=0,a2=1,limit=4294967295;

  unsigned int b;
  while(a1<=limit/2)
  {
    cout<<a2<<" ";
    int sun=a1+a2;

    b=a1;

    a1=a2;
    a2=sun;
   }

  cout<<b/a1<<endl;

  //cout<<a1/a2<<endl;
  return 0;
}

本以为这样就万事欧克了,但是让我没想到的是结果是 0。这是怎么回事呢,仔细看了下程序,哎呀,自己太不注意了,整个数值都定义的是整数型的,当然结果是0了,低级错误啊。

③ 在②的基础上,做如下改动:

#include<iostream>
using namespace std;
int main()
{
  unsigned int a1=0,a2=1,limit=4294967295;

  unsigned int b;
  while(a1<=limit/2)
  {
    cout<<a2<<" ";
    int sun=a1+a2;

    b=a1;

    a1=a2;
    a2=sun;
   }

  cout<<static_cast<double>(b)/a1<<endl;

  //cout<<b/a1<<endl;

  //cout<<a1/a2<<endl;
  return 0;
}

运行的结果为:1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368 75025 121393 196418 317811 514229 832040 1346269 2178309 3524578 5702887 9227465 14930352 24157817 39088169 63245986 102334155 165580141 267914296 433494437 701408733 1134903170 1836311903 2971215073 0.618034

终于出最后的黄金分割点了,哎。。。

原文链接: https://www.cnblogs.com/qlwy/archive/2011/06/28/2121916.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    一个斐波拉契数列的c++程序的思考

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/27770

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月8日 上午5:22
下一篇 2023年2月8日 上午5:22

相关推荐