C语言-初步-级数计算相关

我们来一步一步说明白级数的计算问题。

注意:此处我是以 int 类型 为例子来介绍的。

大家在实战中,往往n的值比较大,使得 n!非常大。就可以试着换成long long int 类型。

一、输入整数n,计算 s,其中 s=1+2+3+...+n

这是一个累加问题,把从1到n累加到s上。

#include<stdio.h>
int main(void)
{
   int n,sum=0,i;
   scanf("%d",&n);
   for(i=1;i<=n;i++)
   {
   	sum=sum+i;
   }
   printf("%d",sum);
   return 0;      

}

二、输入整数n,计算f,其中:f= n!

这是一个累乘问题。

#include<stdio.h>
int main(void)
{
   int n,f=1,i;
   scanf("%d",&n);
   for(i=1;i<=n;i++)
   {
   	f=f*i;
   }
   printf("%d",f);
   return 0;      

}

三、计算s=1!+2!+3!+...+n!

这是一个累加与累乘的混合。

一共是n项,对于第 x 项需要计算 x!,然后累加到总和sum上面。

#include<stdio.h>

int main(void)
{
   int n,sum=0,x,i,f;
   scanf("%d",&n);
   for(x=1;x<=n;x++)
   {//x代表第x项
    //下面的循环用来计算 f=x!
	   	f=1;
	   	for(i=1;i<=x;i++)
	   	{
	   		f=f*i;
	   	}
	   	sum=sum+f;
   }
   printf("%d",sum);
   return 0;      

}

仔细分析一下这 n 项,第 x 项是第 x-1 项的 x 倍,有这样的一个关系,

这样就可以利用上一次计算的x-1项的结果。

#include<stdio.h>

int main(void)
{
   int n,sum=0,x,i,f_x_1,f_x;
   scanf("%d",&n);
   f_x_1=1;//f_x_1初值是1,假设是第0项,第1项是第0项的1倍 
   
   for(x=1;x<=n;x++)
   {
	   	f_x=f_x_1*x;//第x项是第x-1项的x倍	   	
	   	sum=sum+f_x;
	   	f_x_1=f_x;//在下一轮 ,该计算x+1项了,f_x是新的前一项了 
   }
   printf("%d",sum);
   return 0;      

}

等熟悉了,就可以省略掉一个变量,变为:

#include<stdio.h>

int main(void)
{
   int n,sum=0,x,i,f,f_x;
   scanf("%d",&n);
   f_x=1;//fx初值是1,假设是第0项,第1项是第0项的1倍 
   
   for(x=1;x<=n;x++)
   {
	   	f_x=f_x*x;//第x项是第x-1项的x倍	   	
	   	sum=sum+f_x;
	   	 
   }
   printf("%d",sum);
   return 0;      

}

四、更复杂的级数

输入一个n和一个x,n是整数,代表后面一共有n项,x是实数,代表角度,单位是弧度,计算:

 比如 角度为30度的角对应的弧度为 30*pi/180

这个计算比较复杂,有阶乘、有幂,有符号的交替

1、先看最笨的方法。找通项公式。

#include<stdio.h>
#include "math.h"
int main(void)
{
   int n,y,i;
   double f,x,item,sum=0;
   scanf("%d %lf",&n,&x);//输入时x是度数
   x=x*3.1415926/180; 
   f=1;//f初值是1,假设是第0项,第1项是第0项的1倍 
   
   for(i=1;i<=n;i++)
   {
	   	item=pow(-1,i+1)*pow(x,2*i-1);	
        //下面计算(2*i-1)!
		f=1;
		for(y=1;y<=2*i-1;y++)
			f=f*y;
		item=item/f;   	
	   	sum=sum+item;
   }
   printf("%f",sum);
   return 0;      

}

显然,能解决问题,容易理解;

但是双重循环,复杂,且有阶乘的计算,幂的计算,计算量大。

我们可以把求阶乘的功能用函数包装起来,使得形式简单。

2、函数法

#include<stdio.h>
#include "math.h"
int fact(int n)
{
	int f=1,i;
	for(i=2;i<=n;i++)
		f=f*i;
	return f;
}
int main(void)
{
   int n,y,i;
   double x,item,sum=0;
   scanf("%d %lf",&n,&x);//输入时x是度数
   x=x*3.1415926/180; //度数转换为弧度 
   
   for(i=1;i<=n;i++)
   {
	   	item=pow(-1,i+1)*pow(x,2*i-1)/fact(2*i-1);   //第i项的值        	
	   	sum=sum+item;
   }
   printf("%f",sum);
   return 0;      

}

可以看到,引入了求阶乘的函数,main函数的主体就清晰明了很多。

但计算的时间效率却没有改观。

应该考虑前后项之间的关系。

3、前后项法

令第i项是f_i,其x的指数是 2*i-1;

第i-1项是f_i_1, 其x的指数是 2*i-3

有下面的关系

f_i=f_i_1*(-1)*x*x/(2*i-2)/(2*i-1);    

#include<stdio.h>

int main(void)
{
   int n,i;
   double f_i,f_i_1,x,sum=0;
   scanf("%d %lf",&n,&x);//输入时x是度数,n是第几项 
   x=x*3.1415926/180; 
   f_i_1=x;//f初值是x,假设是第1项 
   sum=x;
   if(n==1) 
   {
   	printf("%f\n",sum);
   	return 0;
   }
   
   
   for(i=2;i<=n;i++)
   {
	   	f_i=f_i_1*(-1)*x*x/(2*i-2)/(2*i-1);		   	
	   	sum=sum+f_i;
	   	f_i_1=f_i;
   }
   printf("%f",sum);
   return 0;      

}

4、不走寻常路

前后项法是非常好的一种方法。

但若题目改成这样:

题目描述:根据下面求sin(x)的级数公式,计算sin(x)的值。其中x是弧度。

 比如 角度为30度的角对应的弧度为 30*pi/180

输入:

输入有多行,每一行有两个数,n和x,n代表整数(1<=n<=20),n代表角度,单位是度数。

输出:

对应输入的每一行,输出对应的sin(x),每行输入对应一行输出。

这样这个题目就变成ACM竞赛形式的题目了。

按照前后项的技巧,也需要每行计算n!。

我们可以先计算出所有的n!,记录在数组中。

#include<stdio.h>
#include "math.h"

int main(void)
{
   int n,y,i;
   int fact[21] ={1,1};
   for(i=2;i<=20;i++)
   	fact[i]=fact[i-1]*i;
   	
   	while(1)
   	{
   		double x,item,sum=0;
	   int ret=scanf("%d %lf",&n,&x);//输入时x是度数
	   if(ret!=2)//如果读入的不是两个数,说明没数据了 
	   	break;
	   x=x*3.1415926/180; //度数转换为弧度 
	   
	   
	   double item2=x;//第一项的符号和幂部分之积 
	   sum=x;  //第一项 
	   if(n==1)
	   {
	   	 printf("%f\n",sum);
	   	 continue;
	   }
	   for(i=2;i<=n;i++)
	   {
	   		item2=item2*(-1)*x*x;
		   	item=item2/fact[2*i-1];   //第i项的值   		   	
			 	
		   	sum=sum+item;
	   }
	   printf("%f\n",sum);
	}
   
   
   return 0;      

}

把一些固定不变的值事先计算并记录下来,是一种常用的方法。俗称“查表法”。

  • 14
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值