PTA习题4-3 求分数序列前N项和 (易犯错点讲解以及注意事项)
习题4-3 求分数序列前N项和 (15分)
本题要求编写程序,计算序列 2/1+3/2+5/3+8/5+… 的前N项之和。注意该序列从第2项起,每一项的分子是前一项分子与分母的和,分母是前一项的分子。
输入格式:
输入在一行中给出一个正整数N。
输出格式:
在一行中输出部分和的值,精确到小数点后两位。题目保证计算结果不超过双精度范围。
输入样例:
20
输出样例:
32.66
今天来讲解pta上的一到C语言程序设计编程题-求分数序列前N项和
其实说实话这套题思路没什么讲解可言,但是我今天讲解的是注意事项!
分享我的错误代码
#include<stdio.h>
int main()
{
int n;
scanf("%d",&n);
int a=2,b=1,t,i;
// double a=2,b=1,t,i;//为甚么这里要是double呢?
double sum=2.0;
if(n==1)
{
printf("%0.2lf",sum);
return 0;
}
for(i=2;i<=n;i++)
{
t=a;
a=a+b;
b=t;
sum+=1.0*a/b;
}
printf("%0.2lf",sum);
return 0;
}
乍一看没啥问题,我也是这么觉得,哈哈哈!但是当我执行的时候发现结果如下:
是的,n较大时会不符合结果,于是我就改变范围
#include<stdio.h>
int main()
{
int n;
scanf("%d",&n);
//int a=2,b=1,t,i;
long a=2,b=1,t,i;//***事实证明这句还是会导致n较大时不通过***
long long a=2,b=1,t,i;//*同时事实证明这句还是会导致n较大时不*通过
double sum=2.0;
if(n==1)
{
printf("%0.2lf",sum);
return 0;
}
for(i=2;i<=n;i++)
{
t=a;
a=a+b;
b=t;
sum+=1.0*a/b;
}
printf("%0.2lf",sum);
return 0;
}
接下来我要讲的才是重点,我在百度的时候很多人都没有给出为原因?
大家知道a是斐波那契数列随着n增大会变的非常大的!
我当时认为改变该处的范围就可以啦!但是就是不通过我就纳闷啦!long不行也就罢啦,long long 可是8个字节呀!和double差不多吧!long long 应该必须通过的;
百思不得其解!后来我查书(C语言谭浩强第五版)
long 是4个字节 -2147483648~2147483647
long long 是8个字节 -9223372036854775808~9223372036854775807
即(-2^63 )------- (2^63)-1)
double 是8个字节 2.310^-308----- 1.710^38 (1.7乘以10的38次方)
我总以为8个字节类型差不多,今天算是学到啦!double远远大于long long 的
所以int ,long 以及long long 都是不可以的,我也不知道谁出的题为什么要搞这么大?我无语啦!也许可能出题人本身不知道会这么大,认为该题就是要用double的。怎么会出现整型的呢?只不过我们喜欢一开始用的整型然后1.0*a/b吧!
我看见其他的博客,将double a=2,b=1;然后int t,a是要赋值给t的,最后发现int 不行然后换double t。最后解释(int 为什么不行)说是类型转换导致精度缺失。其实完全是没深入了解。但是不得不承认它的第一步用double a,b,是对的。
其实总的来说
最后一个测试点没有通过就是long long 太小啦!
double才可以满足n较大的情况!
所以a,b,临时变量t都必须要用double
希望我这个解释可以帮到你!
#include<stdio.h>
int main()
{
int n;
scanf("%d",&n);
double a=2,b=1,t,i;
double sum=2.0;
if(n==1)
{
printf("%0.2lf",sum);
return 0;
}
for(i=2;i<=n;i++)
{
t=a;
a=a+b;
b=t;
sum+=1.0*a/b;
}
printf("%0.2lf",sum);
return 0;
}