计算Fibonacci数列前20个数值之和

发布时间:2012-04-10 08:12:34

9-1

问题 计算Fibonacci数列前20个数值之和,其中Fibonacci数列有如下的迭代规律:

第一个元素:

第二个元素:

第三个元素:

……

n个元素:

分析 根据Fibonacci数列的递推规律,必须已知第n-1项和第n-2项之后,才可以计算出第n项。可以同时计算第n1项和第n项序列的值。所需数据与算法如下。

数据要求

问题中的常量:

问题的输入:

int f1=1 /*序列中第1*/

int f2=1 /*序列中第2*/

问题的输出:

unsigned long sum /*序列前20项之和*/

设计 初始算法

1. f1f2初始化为1,并初始化sum的值为sum=0

2. 计算第n-1项并求和,再计算第n项并求和。

3. 循环执行步骤2至求出前20项之和,输出sum

算法细化

1. 初始化:

f1=1;

f2=1;

sum= f1+f2;

n=1n=2f1=1f2=1;因此前两项之和为sum=f1+f2

2. 循环体的语句如下:

f1=f1+f2; /*计算第n-1*/

sum+=f1;

f2=f2+f1; /*计算第n*/

sum+=f2;

n=3f3=f1+f2。如果f3f1表示,则f1=f1+f2;因此前三项之和为sum=sum+f1

n=4f4=f3+f2。如果f3f1表示,f4f2表示,则f2=f2+f1。前四项之和sum=sum+f2

依次类推,可以求解出前n项之和。

3. 由于循环次数已知,因此可以使用for语句。由于循环一次计算2项,因此循环9次可以计算18项数据的和,加上前两项之和,正好为前20项之和。循环条件为

for(i=1;i<10;i++)

{

……

}

流程图

实现 程序代码如下:

#include "stdio.h"

void main()

{

unsigned long f1,f2,sum; /*f1代表第n2项,f2代表第n1项,sum代表和*/

int i;

f1=1;f2=1; /*计算第一项,第二项*/

sum=f1+f2; /*计算第一项与第二项之和*/

for(i=1;i<10;i++) /*累加剩余的18*/

{

f1=f1+f2; /*计算第n1*/

sum+=f1;

f2=f2+f1; /*计算第n*/

sum+=f2;

}

printf("sum=%d",sum);

}

运行结果 sum=17710

测试 如果将数据的声明由数据类型unsigned long改为int,则程序仍然能得到正确的结果;如果再将循环条件改为i<20,即求序列前40项之和,则得到结果3127,显然该结果是一个错误的结果。该测试说明:要注意保存序列和变量的类型,一定要能够容纳最终结果,不要因为超出类型的表示范围而导致错误的结果。

9-2

问题 根据如下的公式计算PI,直到最后一项的绝对值小于

分析 解决此类问题可以进行如下的处理,假设PI= =Y,则Y*6=PI*PI根据题目中公式则有。因此问题的转化为计算Y,求解出Y之后,就可以根据,求解PI。所需数据与算法如下。

数据要求

问题的输入:

unsigned long n; /*公式循环计算变量*/

double sum; /*公式求和变量*/

问题的输出:

double pi; /*根据公式计算出的*/

设计 初始算法

1. 初始化n=1

2. 计算序列第n项的值,如果该值大于等于,则执行下面循环:

sum+=n1

3.结束循环,求解pi

算法细化

1. 循环变量n的初值为1,循环条件,可以进一步转换为

。因此循环结构

for(n=1; n<1000; n++)

{

……

2. 循环体为:

t=1.0/(n*n);

sum+=t;

3. 求解出sum之后,即可计算pi的值,在C程序中没有求根方的运算符,但是在其标准函数库中提供了数学函数sqrt函数,可以实现求根功能。

流程图

实现 程序代码如下:

#include "stdio.h"

#include "math.h"

void main()

{

unsigned long n;

double pi;

double sum=0;

double t;

for(n=1;n<1000;n++)

{

t=1.0/(n*n;

sum+=t;

}

pi=sqrt(6.0*sum);

printf("Pi=%f",pi);

}

运行结果 Pi=3.140637

测试 如果将循环条件改为n<2000,则结果为3.141115,更接近于。该测试说明该程序中循环变量取值范围越大,越能够接近正确结果。

9.3

问题 采用矩形法求定积分

分析 利用矩形法可以求定积分原理如图(9-1)所示。求函数f在(a,b)区间的定积分公式为:

9-1 矩形法求定积分

所需数据与算法如下。

数据要求

问题的输入

double a; /*积分区间下限*/

double b; /*积分区间上限*/

问题的输出

double fx; /*积分结果*/

设计 初始算法

1. 初始化积分区间(ab)。

2. 如果把积分区间划分为100个格,则h=fabs(a-b)/100

3. 因为区间划分为100个格,因此循环过程如下:

for(i=0;i<100;i++)

{

fx=f (x+i*h+h/2);

… …

}

流程图

实现 程序代码如下:

#include "stdio.h"

#include "math.h"

double f (double x)

{

return sin(x);

}

double Jifen(double a,double b)

{

double h;

double fx;

double x;

int i;

double sum=0;

h=fabs(a-b)/100;

x=a;

for(i=0;i<100;i++)

{

fx=f (x+i*h+h/2);

sum=sum+fx;

}

return sum*h;

}

void main()

{

double a;

double b;

double fx;

a=0;

b=3.1415926;

fx=Jifen(a,b);

printf("Ji Fen Y=%f" ,fx);

}

运行结果 Ji Fen Y=2.000082

测试 如果将积分区间划分为1000个格,则循环条件改为i<1000得到结果为2.00001。该测试说明积分区间划分越多,越能够接近正确结果。

9.4 

问题 从键盘读入一段文本,统计其中的英文字母、数字、空格和除此之外的其他字符个数。

分析 由于输入字符的个数不确定,需构建条件循环while((c=getchar())!=EOF)其中EOF为符号常量,用于表示文本输入结束,在PC机上通过输入Ctrl+Z组合键来输入此字符。所需数据与算法如下。

数据要求

问题的输入:

char c; /*获取从键盘上输入的字符*/

问题的输出:

unsigned int nChar; /*文本中英文字母的个数*/

unsigned int nNum; /*文本中数字的个数*/

unsigned int nBlank; /*文本中空格的个数*/

unsigned int nOther; /*文本中其他字符的个数*/

设计 初始算法

1. 初始化变量nCharnNumnBlanknOther为零

2. 从键盘输入文本,直到输入特殊的字符结束

3. 对文本中每一个字符,做循环判断并计数。

算法细化

1. unsigned int nChar=0,nNum=0,nBlank=0,nOther=0;

2. 循环统计从键盘输入的英文字母个数,算法如下:

while((c=getchar())!=EOF)

{

if((c>='a')&&(c<='z')||(c>='A')&&(c<='Z'))

nChar++;

……

流程图

实现 程序代码如下:

#include "stdio.h"

void main()

{

unsigned int nChar=0,nNum=0,nBlank=0,nOther=0;

char c;

while((c=getchar())!=EOF)

{

if((c>='a')&&(c<='z')||(c>='A')&&(c<='Z'))

nChar++;

else

{

if((c>='0')&&(c<='9'))

nNum++;

else

{

if(c==' ')

nBlank++;

else

nOther++;

}

}

}

printf("Char=%d\tNum=%d\tBlank=%d\tOther=%d",nChar,nNum,nBlank,nOther);

}

运行结果

输入 #define PI 3.14^Z

输出 Char=8 Num=3 Blank=2 Other=2

9.14

问题 汉诺(Hanoi)塔问题:古代有一个梵塔,塔内有三个座ABCA座上有64个盘子,盘子大小不等,大的在下,小的在上(如图)。有一个和尚想把这64个盘子从A座移到B座,但每次只能允许移动一个盘子,并且在移动过程中,3个座上的盘子始终保持大盘在下,小盘在上。在移动过程中可以利用B座,要求打印移动的步骤。

9-5汉诺塔问题

分析 递归算法是计算机算法的重要内容,很多问题都可以使用递归方法解决。递归算法的特点是可以比较自然的反映解决问题的过程,并能够便于调试程序。对于某些问题(例如汉诺塔问题,树的遍历等问题),需要通过递归算法求解。所需数据与算法如下。

数据要求

问题的输入:

int n; /*盘子数*/

问题的输出:

char chSour; /*盘子所在源座*/

char chDest; /*盘子移动后的目标座*/

设计 初始算法

1. 输入盘子数n

2. 利用递归算法移动盘子

算法细化

这个问题在盘子比较多的情况下,很难直接写出移动步骤。我们可以先分析盘子比较少的情况。假定盘子从大向小依次为:盘子1,盘子2...,盘子64

如果只有一个盘子,则不需要利用B座,直接将盘子从A移动到C

如果有2个盘子,可以先将盘子1上的盘子2移动到B;将盘子1移动到c;将盘子2移动到c。这说明了:可以借助B2个盘子从A移动到C,当然,也可以借助C2个盘子从A移动到B

如果有3个盘子,那么根据2个盘子的结论,可以借助c将盘子1上的两个盘子从A移动到B;将盘子1A移动到CA变成空座;借助A座,将B上的两个盘子移动到C。这说明:可以借助一个空座,将3个盘子从一个座移动到另一个。

如果有4个盘子,那么首先借助空座C,将盘子1上的三个盘子从A移动到B;将盘子1移动到CA变成空座;借助空座A,将B座上的三个盘子移动到C

上述的思路可以一直扩展到64个盘子的情况:可以借助空座C将盘子1上的63个盘子从A移动到B;将盘子1移动到CA变成空座;借助空座A,将B座上的63个盘子移动到C

归纳成递归公式,可以写成:

其中,Hanoi函数的第一个参数表示盘子的数量,第二个参数表示源座,第三个参数表示借用的座,第四个参数代表目的座。比如Hanoi(n-1,A,C,B)表示借助C座把n-1个盘子从A座移动到B座。

Move函数的第一个参数表示源座,第二个参数代表目的座。Move函数的功能是将源座最上面的一个盘子移动到目的座上。

流程图

实现 程序代码如下:

void Move(char chSour, char chDest)

{

/*打印移动步骤*/

printf("\nMove the top plate of %c to %c",chSour, chDest);

}

Hanoi(int n, char chA, char chB, char chC)

{

/*检查当前的盘子数量是否为1*/

if(n==1) /*盘子数量为1,打印结果后,不再继续进行递归*/

Move(chA,chC);

else/*盘子数量大于1,继续进行递归过程*/

{

Hanoi(n-1,chA,chC,chB);

Move(chA,chC);

Hanoi(n-1,chB,chA,chC);

}

}

main()

{

int n;

/*输入盘子的数量*/

printf("\nPlease input number of the plates: ");

scanf("%d",&n);

printf("\nMoving %d plates from A to C:",n);

/*调用函数计算,并打印输出结果*/

Hanoi(n,'A','B','C');

}

运行结果

如果n4,程序输出结果为:

Moving 4 plates from A to C:

Move the top plate of A to B

Move the top plate of A to C

Move the top plate of B to C

Move the top plate of A to B

Move the top plate of C to A

Move the top plate of C to B

Move the top plate of A to B

Move the top plate of A to C

Move the top plate of B to C

Move the top plate of B to A

Move the top plate of C to A

Move the top plate of B to C

Move the top plate of A to B

Move the top plate of A to C

Move the top plate of B to C

测试 当输入的盘子数过多时,如64,程序运行很慢。递归过程实现的程序结构清晰,程序简单,但执行速度慢。

计算Fibonacci数列前20个数值之和

相关推荐