镜缘浮影 小人本住在 苏州的城外 家里有屋又有田 生活乐无边

那些年我们一起忘掉的C (四).分数数列求和

2016-11-21
wilmosfang
c
原文地址 http://soft.dog/2016/11/21/c-basic-04/

前言

数组与函数递归调用是C语言中很重要的组成部分,算数计算过程中也要留意对象的数据类型对于结果的影响


概要


求特定数列的前20项之和

有一个数列如下:

2/1, 3/2, 5/3, 8/5, 13/8, 21/13,……

要求出这个数列的前20项之和

代码注解

直接求解

#include <stdio.h>

void main()
{
	int fz=2,fm=1,i,tmp;  //定义四个整型变量,分别存放分子分母,循环控制,与临时数值,初始化第一个数的分子分母
	float sum=0; //定义一个浮点变量来存放累加和,并且初始化为0 
	for (i=0;i<20;i++) //进行20次循环
	{
		sum+=(float)fz/fm; //将分子转为浮点数与分母相除,结果累加到sum中,必须进行数据类型转换,否则整型相除的结果为整,丢失掉小数点后的精度
		tmp=fz;
		fz+=fm;
		fm=tmp; // 这三步是在生成下一个分数的分子和分母,为下一次循环作准备工作
	}
	printf("%f\n",sum);
}

使用递归

#include <stdio.h>

int fz(int n) //定义一个分子函数,接收一个整型参数,其实就是位置值,返馈一个整型值,也就是这个位置的分子值
{
	return (n==1)?2:((n==2)?3:(fz(n-1)+fz(n-2))); //如果n值为1时,函数值为2,如果n值为2时,函数值为3,其它的为这个数前两个函数值之和
}
	
int fm(int n)
{
	return (n==1)?1:((n==2)?2:(fm(n-1)+fm(n-2))); //如果n值为1时,函数值为1,如果n值为2时,函数值为2,其它的为这个数前两个函数值之和
} 	

void main() //当main函数放在最后时(被调用函数定义在前),可以不必对其中使用到的其它函数进行声明,如果main函数在前,就必须在使用前进行声明
{
	int i; //定义一个整型变量来进行遍历与循环控制
	float sum=0; //定义一个变量来存储累计和,由于是分数值,所以应该使用浮点数来存储
	for (i=1;i<21;i++) sum+=(float)fz(i)/fm(i); //i赋初值1,在[1,20]的范围里,i会逐一自增;然后将分子分母的值相除,结果累加到sum中,由于fz(i),fm(i)的值都是整型,整型之间相除结果仍然为整型,这样会丢失小数点后的精度,(float)fz(i)的操作可以强制将fz(i)的整型值转化为浮点型,然后浮点型与整型相除结果就是浮点型
	printf("%f\n",sum);	
}

使用数组

#include <stdio.h>

void main()
{
	int i;  //定义一个整型变量进行遍历与循环控制
	float fz[20]={2,3},fm[20]={1,2},sum=0;  //定义两个包含20个元素的浮点数组,和一个存放累积和的变量,分别给两个数组前两个元素赋初值,将累积和初值置零
	for (i=2;i<20;i++) fz[i]=fz[i-1]+fz[i-2];  //初始化分子数组中的剩余元素
	for (i=2;i<20;i++) fm[i]=fm[i-1]+fm[i-2];  //初始化分母数组中的剩余元素
	for (i=0;i<20;i++) sum+=fz[i]/fm[i];  //将所有分子分母分别相除并且将结果累加到sum中
	printf("%f\n",sum);
}

两种实现方式的区别是什么呢

使用数组会消耗更多存储空间,但比较快;使用递归函数会消耗更多CPU时间,但比较省存储空间

一个是在拿空间换时间,一个是在拿时间换空间

思路

观察数列特征是第一步,发现除了第一个分数,后面的每一个分数分子都是前一个分数的分子分母之和,而分母则是前一个分数的分子

这个数列有些类似于取斐波那契数列的前20项之和,既可以先将这个数列进行构建,存储,然后遍历相加

也可以实现出函数,进行遍历累加

基础知识点

  • 数值类型的转化
  • 函数的定义
  • 函数的递归调用
  • 数组的定义与赋值
原文地址 http://soft.dog/2016/11/21/c-basic-04/

评论