计算Fibonacci数列前20个数值之和.docx
《计算Fibonacci数列前20个数值之和.docx》由会员分享,可在线阅读,更多相关《计算Fibonacci数列前20个数值之和.docx(16页珍藏版)》请在冰豆网上搜索。
计算Fibonacci数列前20个数值之和
9-1
问题计算Fibonacci数列前20个数值之和,其中Fibonacci数列有如下的迭代规律:
第一个元素:
第二个元素:
第三个元素:
……
第n个元素:
分析根据Fibonacci数列的递推规律,必须已知第n-1项和第n-2项之后,才可以计算出第n项。
可以同时计算第n-1项和第n项序列的值。
所需数据与算法如下。
数据要求
问题中的常量:
无
问题的输入:
intf1=1/*序列中第1项*/
intf2=1/*序列中第2项*/
问题的输出:
unsignedlongsum/*序列前20项之和*/
设计初始算法
1.f1和f2初始化为1,并初始化sum的值为sum=0。
2.计算第n-1项并求和,再计算第n项并求和。
3.循环执行步骤2至求出前20项之和,输出sum。
算法细化
1.初始化:
f1=1;
f2=1;
sum=f1+f2;
当n=1,n=2时f1=1,f2=1;因此前两项之和为sum=f1+f2。
2.循环体的语句如下:
f1=f1+f2;/*计算第n-1项*/
sum+=f1;
f2=f2+f1;/*计算第n项*/
sum+=f2;
当n=3时f3=f1+f2。
如果f3用f1表示,则f1=f1+f2;因此前三项之和为sum=sum+f1。
当n=4时f4=f3+f2。
如果f3用f1表示,f4用f2表示,则f2=f2+f1。
前四项之和为sum=sum+f2。
依次类推,可以求解出前n项之和。
3.由于循环次数已知,因此可以使用for语句。
由于循环一次计算2项,因此循环9次可以计算18项数据的和,加上前两项之和,正好为前20项之和。
循环条件为
for(i=1;i<10;i++)
{
……
}
流程图
实现程序代码如下:
#include"stdio.h"
voidmain()
{
unsignedlongf1,f2,sum;/*f1代表第n-2项,f2代表第n-1项,sum代表和*/
inti;
f1=1;f2=1;/*计算第一项,第二项*/
sum=f1+f2;/*计算第一项与第二项之和*/
for(i=1;i<10;i++)/*累加剩余的18项*/
{
f1=f1+f2;/*计算第n-1项*/
sum+=f1;
f2=f2+f1;/*计算第n项*/
sum+=f2;
}
printf("sum=%d",sum);
}
运行结果sum=17710
测试如果将数据的声明由数据类型unsignedlong改为int,则程序仍然能得到正确的结果;如果再将循环条件改为i<20,即求序列前40项之和,则得到结果3127,显然该结果是一个错误的结果。
该测试说明:
要注意保存序列和变量的类型,一定要能够容纳最终结果,不要因为超出类型的表示范围而导致错误的结果。
9-2
问题根据如下的公式计算PI,直到最后一项的绝对值小于
分析解决此类问题可以进行如下的处理,假设PI=
,
=Y,则有Y*6=PI*PI,根据题目中公式则有
。
因此问题的转化为计算Y,求解出Y之后,就可以根据
,求解PI。
所需数据与算法如下。
数据要求
问题的输入:
unsignedlongn;/*公式循环计算变量*/
doublesum;/*公式求和变量*/
问题的输出:
doublepi;/*根据公式计算出的
值*/
设计初始算法
1.初始化n=1。
2.计算序列第n项的值
,如果该值大于等于
,则执行下面循环:
sum+=
;n加1;
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"
voidmain()
{
unsignedlongn;
doublepi;
doublesum=0;
doublet;
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矩形法求定积分
所需数据与算法如下。
数据要求
问题的输入:
doublea;/*积分区间下限*/
doubleb;/*积分区间上限*/
问题的输出:
doublefx;/*积分结果*/
设计初始算法
1.初始化积分区间(a,b)。
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"
doublef(doublex)
{
returnsin(x);
}
doubleJifen(doublea,doubleb)
{
doubleh;
doublefx;
doublex;
inti;
doublesum=0;
h=fabs(a-b)/100;
x=a;
for(i=0;i<100;i++)
{
fx=f(x+i*h+h/2);
sum=sum+fx;
}
returnsum*h;
}
voidmain()
{
doublea;
doubleb;
doublefx;
a=0;
b=3.1415926;
fx=Jifen(a,b);
printf("JiFenY=%f",fx);
}
运行结果JiFenY=2.000082
测试如果将积分区间划分为1000个格,则循环条件改为i<1000,得到结果为2.00001。
该测试说明积分区间划分越多,越能够接近正确结果。
9.4
问题从键盘读入一段文本,统计其中的英文字母、数字、空格和除此之外的其他字符个数。
分析由于输入字符的个数不确定,需构建条件循环while((c=getchar())!
=EOF),其中EOF为符号常量,用于表示文本输入结束,在PC机上通过输入Ctrl+Z组合键来输入此字符。
所需数据与算法如下。
数据要求
问题的输入:
charc;/*获取从键盘上输入的字符*/
问题的输出:
unsignedintnChar;/*文本中英文字母的个数*/
unsignedintnNum;/*文本中数字的个数*/
unsignedintnBlank;/*文本中空格的个数*/
unsignedintnOther;/*文本中其他字符的个数*/
设计初始算法
1.初始化变量nChar、nNum、nBlank、nOther为零
2.从键盘输入文本,直到输入特殊的字符结束
3.对文本中每一个字符,做循环判断并计数。
算法细化
1.unsignedintnChar=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"
voidmain()
{
unsignedintnChar=0,nNum=0,nBlank=0,nOther=0;
charc;
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);
}
运行结果
输入#definePI3.14^Z
输出Char=8Num=3Blank=2Other=2
9.14
问题汉诺(Hanoi)塔问题:
古代有一个梵塔,塔内有三个座A、B、C,A座上有64个盘子,盘子大小不等,大的在下,小的在上(如图)。
有一个和尚想把这64个盘子从A座移到B座,但每次只能允许移动一个盘子,并且在移动过程中,3个座上的盘子始终保持大盘在下,小盘在上。
在移动过程中可以利用B座,要求打印移动的步骤。
A
B
C
图9-5汉诺塔问题
分析递归算法是计算机算法的重要内容,很多问题都可以使用递归方法解决。
递归算法的特点是可以比较自然的反映解决问题的过程,并能够便于调试程序。
对于某些问题(例如汉诺塔问题,树的遍历等问题),需要通过递归算法求解。
所需数据与算法如下。
数据要求
问题的输入:
intn;/*盘子数*/
问题的输出:
charchSour;/*盘子所在源座*/
charchDest;/*盘子移动后的目标座*/
设计初始算法
1.输入盘子数n
2.利用递归算法移动盘子
算法细化
这个问题在盘子比较多的情况下,很难直接写出移动步骤。
我们可以先分析盘子比较少的情况。
假定盘子从大向小依次为:
盘子1,盘子2,...,盘子64。
如果只有一个盘子,则不需要利用B座,直接将盘子从A移动到C。
如果有2个盘子,可以先将盘子1上的盘子2移动到B;将盘子1移动到c;将盘子2移动到c。
这说明了:
可以借助B将2个盘子从A移动到C,当然,也可以借助C将2个盘子从A移动到B。
如果有3个盘子,那么根据2个盘子的结论,可以借助c将盘子1上的两个盘子从A移动到B;将盘子1从A移动到C,A变成空座;借助A座,将B上的两个盘子移动到C。
这说明:
可以借助一个空座,将3个盘子从一个座移动到另一个。
如果有4个盘子,那么首先借助空座C,将盘子1上的三个盘子从A移动到B;将盘子1移动到C,A变成空座;借助空座A,将B座上的三个盘子移动到C。
上述的思路可以一直扩展到64个盘子的情况:
可以借助空座C将盘子1上的63个盘子从A移动到B;将盘子1移动到C,A变成空座;借助空座A,将B座上的63个盘子移动到C。
归纳成递归公式,可以写成:
其中,Hanoi函数的第一个参数表示盘子的数量,第二个参数表示源座,第三个参数表示借用的座,第四个参数代表目的座。
比如Hanoi(n-1,A,C,B)表示借助C座把n-1个盘子从A座移动到B座。
Move函数的第一个参数表示源座,第二个参数代表目的座。
Move函数的功能是将源座最上面的一个盘子移动到目的座上。
流程图
实现程序代码如下:
voidMove(charchSour,charchDest)
{
/*打印移动步骤*/
printf("\nMovethetopplateof%cto%c",chSour,chDest);
}
Hanoi(intn,charchA,charchB,charchC)
{
/*检查当前的盘子数量是否为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()
{
intn;
/*输入盘子的数量*/
printf("\nPleaseinputnumberoftheplates:
");
scanf("%d",&n);
printf("\nMoving%dplatesfromAtoC:
",n);
/*调用函数计算,并打印输出结果*/
Hanoi(n,'A','B','C');
}
运行结果
如果n为4,程序输出结果为:
Moving4platesfromAtoC:
MovethetopplateofAtoB
MovethetopplateofAtoC
MovethetopplateofBtoC
MovethetopplateofAtoB
MovethetopplateofCtoA
MovethetopplateofCtoB
MovethetopplateofAtoB
MovethetopplateofAtoC
MovethetopplateofBtoC
MovethetopplateofBtoA
MovethetopplateofCtoA
MovethetopplateofBtoC
MovethetopplateofAtoB
MovethetopplateofAtoC
MovethetopplateofBtoC
测试当输入的盘子数过多时,如64,程序运行很慢。
递归过程实现的程序结构清晰,程序简单,但执行速度慢。