第
3 
章累加法

3.算法设计思想
1 

累加是程序设计中最常遇见的问题,例如求某班级学生考试的总平均
分;求某单位支出的总薪资等。累加是指在一个值的基础上重复加上其他
值,典型的应用有求和、计数(统计出现的次数)等。

累加法的一般格式为S=S+T,其中,变量
S 
是累加器,一般初值取
0;
T 
为每次的累加项,通过累加项
T 
的不断变化,将所有的
T 
值都累加到
累加器
S 
中。

注意:格式中的两个
S 
是不同的。“=”后面的
S 
代表的是原来的值, 
而“=”前面的
S 
是
S 
的原来值与累加项
T 
的和。也就是说,
S 
保存累加
过程中的中间结果和最后结果;通常,累加项
T 
的变化是有规律的,在设计
算法时就是要找到其变化规律。

累加法一般由循环结构来实现,在设计循环算法时,需要确定以下3 
方面的内容。

(1)循环控制变量的初值、终值和步长。
(2)循环体的内容(一般包括语句:S=S+T;)。
(3)循环结束条件(一般与
T 
有关)。
3.典型例题
2 

3.2.1 
自然数求和
1. 
问题描述
求1+2+3+…+
n 
并输出结果。

2. 
问题分析
这是对自然数进行累加的问题,需要重复进行
n 
次(或n-1次)加法
运算,显然可以用循环结构来实现。重复执行循环体
n 
次(或n-1次), 每
次加一个数;可以看出每次相加的数是上一次的数加1。使用一个变量
s 
作为累加器,用于记录累加的中间结果和最终结果,初始值为0;使用一个


38  算法设计方法与优化(第2 版) 
变量t 作为循环控制变量,t 初始值为1;将t 与s 相加,结果保存到s 中,然后t 增加1,再与
s 相加,不断重复,直到t 的值超过n 为止,结束循环。最后s 保存的即为最终的累加和。
3.算法说明
算法说明参见表3-1。 
表 3-1 
类 型名 称代表的含义
算法 add(intn) 求自然数的累加和
形参变量n 自然数,进行累加的最大数
变量 s 累加器(和),存放累加结果
变量 t 循环控制变量
4.算法设计 
#include "stdio.h" 
int add(int n) 
{ 
int s=0; 
int t; /*用于保存逐步增加自然数的变量t 赋初值为1*/ 
for(t=1;t<=n;t++) /*t 从1 到n 执行循环体语句实现求和*/ 
{ 
s=s+t; 
} 
return s; /*返回1 到n 的自然数之和*/ 
}v
oid main() 
{ 
int s=0; /*用于保存累加结果,初始值为0*/ 
int n; /*用来存储用户输入的最大加数*/ 
printf("input a number:\n"); 
scanf("%d",&n); /*获取最大加数,保存到变量n 中*/ 
s=add(n); 
printf("1 到%d 的和为:%d\n",n,s); 
} 
5.运行结果
6.算法优化
1)优化说明
利用数学知识进行算法优化。通过对自然数累加的分析可以看出,每次相加的数比
上一次的数大1,即各项加数形成一个差为1的等差数列。根据等差数列求和公式:(首

第3 章 累加法  39 
项+末项)×项数/2,可得自然数的累加和。
2)算法说明
算法说明参见表3-2。 
表 3-2 
类 型名 称代表的含义
算法 add(intn) 求自然数的累加和
形参变量n 自然数,进行累加的最大数
变量 s 累加器(和),存放累加结果 
3)算法设计 
#include "stdio.h" 
int add(int n) 
{ 
int s; 
s=(1+n)*n/2; /*利用数学公式(首项+末项)×项数/2 来替代for 循环*/ 
return s; 
} 
3.2.2 自然数倒数求和
1.问题描述 
求1/1+1/2+1/3+…+1/n,要求累加项精确到10-6,并输出结果。
2.问题分析
求解本问题可使用do-while循环,循环体中实现累加求和。加数t 为1/n,n 的值从
1开始,每次循环n 的值增加1,并在每次求和后判定循环条件。根据题意,要求精度到
10-6,则循环终止条件为1/n<10-6。
3.算法说明
算法说明参见表3-3。 
表 3-3 
类 型名 称代表的含义
算法fun() 求自然数倒数之和
变量s 累加器(和),存放累加结果
变量t 累加项
变量n 循环控制变量
4.算法设计 
#include "stdio.h" 
double fun()

40  算法设计方法与优化(第2 版) 
{ 
double s=0,t; 
int n=1; 
do 
{ 
t=1.0/n; 
s=s+t; 
n++; 
}while(t>=0.000001); /*t 的值大于精确度时执行循环体*/ 
return s; 
}v
oid main() 
{ 
double s=0; 
s=fun(); 
printf(" 1/1+1/2+1/3+…+1/n=%f\n",s); 
} 
5.运行结果
6.算法优化
优化说明: 
(1)题中要求累加项精确到10-6,可以直接将它表示成小数形式0.000001,但其中0 
比较多时,容易出错;这时建议用指数形式表示为1e-6。
(2)算法中“t=1.0/n;”不能写成“t=1/n;”,这是因为C语言有整除和实除之分。
(3)算法中“t=1.0/n;n++;”可简写为“t=1.0/(n++);”,在C语言中,“++i;” 
是使用i之前,先使i的值加1。“i++;”在使用i之后,对i的值加1,因此等价。
3.2.3 统计及格人数
1.问题描述 
一次考试共考了语文、代数和外语三科。某小组共有9人,考后各科及格人数名单如
表3-4所示,请编写算法找出三科全及格的学生的学号,并统计全部及格的人数。
表 3-4 
科目及格学生的学号科目及格学生的学号
语文1,9,6,8,4,3,7 外语8,1,6,7,3,5,4,9 
代数5,2,9,1,3,7 
2.问题分析
从语文名单中逐一抽出及格学生学号,先在代数名单中查找,若有该学号,说明代数

第3 章 累加法  41 
也及格了,再在外语名单中继续查找,看该学号学生是否外语也及格了,若仍在,说明该学
号学生三科全及格,否则至少有一科不及格。语文名单中没有的学号,不可能三科全及
格,因此,语文名单处理完算法就可以结束了。
3.算法说明
算法说明参见表3-5。 
表 3-5 
类 型名 称代表的含义
算法check() 判断三门课程是否都及格
数组a,b,c 分别存储语文、代数、外语及格的学号
变量count 统计三门都及格的人数
变量flag 标志变量
4.算法设计 
#include "stdio.h" 
int a[7],b[6],c[8],count=0; 
int check() 
{ 
int i,j,k,temp; 
for(i=0;i<7;i++) 
{ 
temp=a[i]; 
for(j=0;j<6;j++) 
if(temp==b[j]) 
for(k=0;k<8;k++) 
if(temp==c[k]) 
{ 
count++; 
printf("%-4d",temp); 
break; 
} 
} 
printf("\n"); 
return count; 
}i
nt main() 
{ 
int i; 
printf("请输入语文及格的学号:"); 
for(i=0;i<7;i++) 
scanf("%d",&a[i]);

42  算法设计方法与优化(第2 版) 
printf("请输入代数及格的学号:"); 
for(i=0;i<6;i++) 
scanf("%d",&b[i]); 
printf("请输入外语及格的学号"); 
for(i=0;i<8;i++) 
scanf("%d",&c[i]); 
check(); 
if(count==0) 
printf("no.\n"); 
else 
printf("全部及格的人数为:%d\n",count); 
} 
5.运行结果
6.算法优化
1)优化说明
本题统计三科及格学生名单,因为有9名学生,可以开辟9个元素的数组a[],作为
各学号考生及格科目的计数器。将三科及格名单通过键盘输入,无须用数组存储,只要同
时用数组a 累加对应学号的及格科目个数即可。最后,凡计数器的值等于3,就是全及格
的学生,否则,至少有一科不及格。
2)算法说明
算法说明参见表3-6。
表 3-6 
类 型名 称代表的含义
算法check() 判断三门课程是否都及格
数组a[10] 下标为学号,元素值为该考生及格科目的计数器
变量count 统计三门都及格的人数
变量flag 标志变量 
3)算法设计 
#include "stdio.h" 
int count=0,xh, a[10]={ 0 }; 
int check() 
{ 
for(xh=1;xh<=9;xh++)

第3 章 累加法  43 
if(a[xh]==3) 
{ 
count++; 
printf("%-4d",xh); 
} 
printf("\n"); 
return count; 
}i
nt main() 
{ 
int i; 
printf("请依次输入及格的学号:"); 
for(i=1;i<=21;i++) 
{ 
scanf("%d",&xh); 
a[xh]++; 
} 
check(); 
if(count==0) 
printf("no.\n"); 
else 
printf("及格人数为:%d 人\n",count); 
} 
3.2.4 计算π值
1.问题描述 
利用公式π/4=1-1/3+1/5-1/7+…计算π的近似值,要求项的绝对值小于10-6, 
输出结果保留6位小数。
2.问题分析
根据已知公式,关键是求出多项式的值。经过观察发现多项式的各项是有规律的: 
一是各项符号先正后负依次交替;二是每项的分子都是1;三是后一项的分母是前一项分
母加2。
找到这些规律就可以用累加法设计算法了。首先设置一个符号变量sign,用来标记
各项的符号,使用“sign=-sign;”语句进行符号交替变换;其次使用一个循环变量i表示
分母,i的初值为1,其变化规律是语句“i=i+2;”,因此通项即可表示为t=sign*1.0/i。
再次设累加器变量pi,用来表示π值,计算方法是语句“pi=pi+t;”,最后循环的终止条件
是“fabs(t)<1e-6”,最后求得π值为pi*=4。
注意:fabs(x)是求实数x绝对值的库函数,使用时要包含“math.h”头文件。
3.算法说明
算法说明参见表3-7。

44  算法设计方法与优化(第2 版) 
表 3-7 
类 型名 称代表的含义
算法fun() 求π的近似值
变量pi 累加器,保存π值
变量i 循环变量,保存每项的分母
变量sign 标记符号,用来记录多项式的符号
变量t 表示多项式的项
4.算法设计 
#include "stdio.h" 
#include "math.h" 
double fun() 
{ 
long i; 
int sign=1; 
double pi=0,t=1; 
i=1; 
do 
{ 
pi=pi+t; 
i+=2; 
sign=-sign; /*用来记录加数的符号*/ 
t=sign*1.0/i; 
}while(fabs(t)>=1e-6); /*判断终止条件*/ 
pi*=4; 
return pi; 
}v
oid main() 
{ 
double pi; 
pi=fun(); 
printf("π=%.6f\n",pi); /*结果保留6 位小数*/ 
} 
5.运行结果
3.2.5 数位求和
1.问题描述 
给定一个int类型的整数n,求这个整数的各位数之和。例如:123表示计算1+2+ 
3的值,这个整数的各位数之和就是6。

第3 章 累加法  45 
2.问题分析
要想得到整数的各位数,可以利用数组将整数的各位数存入数组中,最后再遍历数组
求和。接
下来的关键是如何获得这个整数的各位数。
假如这个整数是102×a+10×b+c,它的各位数就是a,b,c,我们只需要将102× 
a+10×b+c 模除10就可以得到c,并且102×a+10×b+c 变为新的整数10×a+b,我
们再将10×a+b 模除10就可以得到b,并且10×a+b 变为新的整数a,即得到整数
102×a+10×b+c 的各位数a,b,c。
3.算法说明
算法说明参见表3-8。 
表 3-8 
类 型名 称代表的含义
算法getNum(intm) 求数位之和
形参变量m 输入的int类型的数
变量len int类型数的长度
变量sum 各位数之和
一维数组num 存储int类型数的各位
4.算法设计 
int getNum(int m) 
{ 
int len =0, num[20], i, sum =0; 
while (m) 
{ 
num[len] =m %10; /*存储m 的最后一位*/ 
len++; 
m /=10; /*除10,最后一位进行更新*/ 
} 
for (i =0; i <len; i++) 
{ 
sum +=num[i]; /*利用sum 进行累加求和*/ 
} 
return sum; 
}i
nt main() 
{ 
int n; 
scanf("%d", &n); 
printf("%d", getNum(n));

46  算法设计方法与优化(第2 版) 
return 0; 
} 
5.运行结果
6.算法优化
1)优化说明
根据题意,只需要得到int类型的数的各位数之和就可以,前一个算法利用数组进行
求和,结果虽然正确,但是算法效率低。在此可以不设置数组存储整数的各位数,直接利
用sum 对取出来的数字进行累加求和。
2)算法说明
算法说明参见表3-9。 
表 3-9 
类 型名 称代表的含义
算法getNum(intm) 求数位之和
形参变量m 输入的int类型的数
变量n 输入的int类型的数
变量sum 各位数之和 
3)算法设计 
#include "stdio.h" 
int getNum(int m) 
{ 
int sum =0; 
while (m) 
{ 
sum +=m %10; /*对sum 进行累加求和*/ 
m /=10; 
} 
return sum; 
}i
nt main() 
{ 
int n; 
scanf("%d", &n); 
printf("%d", getNum(n));

第3 章 累加法  47 
return 0; 
} 
3.2.6 小鱼游泳问题
1.问题描述 
有一条小鱼,它平日每天游泳250千米,周末休息(实行双休日),假设从周n 开始算
起,过了k 天以后,小鱼一共累计游泳了多少千米呢? 
2.问题分析
本题表明除了周末每天游泳250千米,那么问题的关键在于判断周末,假设小鱼从周
n 开始,一共游泳k 天,用i 控制循环次数,每游一天n 就加上1,累加器s 加上250,当n=6 
或者n=7,就证明是周末,只需改变n。
3.算法说明
算法说明参见表3-10。 
表 3-10 
类 型名 称代表的含义
算法fun(intn,intk) 求解小鱼游泳问题
形参变量n 周几开始游
形参变量k 游几天
变量s 累加器(和),存放累加结果
4.算法设计 
#include<stdio.h> 
int fun(int n,int k) 
{ 
int s =0; /*游了s 千米*/ 
for (int i =1; i <=k; i++) /*要游k 天*/ 
{ 
if (n ! =6 && n ! =7) /*如果不是周末,加250*/ 
s +=250; 
if (n ==7) 
n =1; /*如果是周日,n 赋值1*/ 
else 
n++; /*否则n++*/ 
} 
return s; 
}i
nt main() 
{

48  算法设计方法与优化(第2 版) 
int n, k; /*周n 开始游,过了k 天*/ 
scanf("%d%d", &n, &k); 
printf("游了%d 千米", fun(n,k)); /*输出游的千米数*/ 
return 0; 
} 
5.运行结果
6.算法优化
1)优化说明
不难想到,当游到周六(即n=6)和周日(即n=7)时,小鱼游的千米数(累加器s)没
有变化,因此可以通过适当的改变,跳过周日的情况。
2)算法说明
算法说明同上。
3)算法设计 
#include<stdio.h> 
int fun(int n,int k) 
{ 
int s =0; /*游了s 千米*/ 
for (int i =1; i <=k; i++) /*要游k 天*/ 
{ 
if (n !=6 && n !=7) /*如果不是周末,加250*/ 
s +=250; 
if (n ==6) /*如果是周六*/ 
{ 
n =1; /*跳过周日到周一*/ 
i++; /*在for 循环i++的基础上再i++,跳过周日*/ 
} 
else 
n++; /*否则n++*/ 
} 
return s; 
}i
nt main() 
{ 
int n, k; /*周n 开始游,过了k 天*/ 
scanf("%d%d", &n, &k);

第3 章 累加法  49 
printf("游了%d 千米", fun(n,k)); /*输出游的千米数*/ 
return 0; 
} 
3.2.7 判断天数
1.问题描述 
输入一个年月日,格式如2013/5/15,判断这一天是这一年的第几天。
2.问题分析
首先对输入的年份进行判断,是闰年还是平年,闰年二月是29天,平年二月是28天。
其次对输入的月份进行判断,假如输入的是5月,则把1、2、3、4四个月份的天数加在一
起,最后再加上日(几号)的值,则可得到这个日期是该年的第几天。
3.算法说明
算法说明参见表3-11。 
表 3-11 
类 型名 称代表的含义
算法day(inty,intm,intd) 判断天数
形参变量y,m,d 年、月、日
变量sum 统计天数
4.算法设计 
#include "stdio.h" 
int day(int y,int m,int d) 
{ 
int sum=0; 
switch(m-1) 
{ 
case 11:sum+=30; 
case 10:sum+=31; 
case 9:sum+=30; 
case 8:sum+=31; 
case 7:sum+=31; 
case 6:sum+=30; 
case 5:sum+=31; 
case 4:sum+=30; 
case 3:sum+=31; 
case 2:sum+=28; 
case 1:sum+=31; 
}

50  算法设计方法与优化(第2 版) 
if(m>2) 
if((y%4==0&&y%100!=0)||(y%400==0)) 
sum++; 
sum+=d; 
return(sum); 
}m
ain() 
{ 
int y,m,d; 
printf(" Input date:(eg. 2013/5/5): "); 
scanf("%d/%d/%d",&y,&m,&d); 
printf(" day=%d\n",day(y,m,d)); 
} 
5.运行结果
6.算法优化
1)优化说明
首先将每个月份的天数保存到数组a 中。对输入的月份进行判断,假如输入的是
5月,则把1、2、3、4四个月份的天数加在一起,然后对输入的年份进行判断,若闰年二
月是29天,则天数增加1。最后再加上日(几号)的值,就可得到这个日期是该年的第
几天。
2)算法说明
算法说明参见表3-12。
表 3-12 
类 型名 称代表的含义
算法day(inty,intm,intd) 判断天数
形参变量y,m,d 年、月、日
一维数组a 存储每月的天数
变量sum 统计天数 
3)算法设计 
#include "stdio.h" 
int day(int y,int m,int d) 
{ 
int a[12]={31,28,31,30,31,30,31,31,30,31,30,31}; 
int i,sum=0; 
for(i=0;i<m-1;i++)

第3 章 累加法  51 
sum=sum+a[i]; 
if(m>2) 
if((y%4==0&&y%100!=0)||(y%400==0)) 
sum++; 
sum=sum+d; 
return(sum); 
} 
3.3 小 结
本章讲解了算法设计方法中的累加法,并结合一些具体的问题来分析和设计算法。
重点要理解累加法的设计思想,并能够运用它解决实际问题。
累加法的基本思想是:首先设置累加器S,根据情况将初值赋0或一个特定值;其次
定义一个变量T 存放累加项,针对具体问题找出T 的变化规律;最后,在循环体中执行
S=S+T ,直到满足循环结束条件为止。
如果循环次数确定,那么累加法设计的一般过程如下(假设累加次数为n 次): 
/*其他语句*/ 
S=0; 
for(i=1; i<=n; i++) 
{ 
计算累加项T 的值 
S=S+T; 
}
如果循环次数不确定,则累加法设计的一般过程如下: 
/*其他语句*/ 
S=0; 
do 
{ 
计算累加项T 的值 
S=S+T; 
}w
hile(循环结束条件); 
习 题
3-1 求1-2+3-4+5-6+…+99-100。
3-2 求1-1/2+1/3-1/4+…-1/100。
3-3 求100以内所有素数的和。

52  算法设计方法与优化(第2 版) 
3-4 求100以内所有奇数的和。即1+3+5+…+99。
3-5 编程计算(1+2)+(2+3)+(3+4)+…+(20+21)+(21+22)的值。
3-6 编写一个程序,计算半径分别为0.5mm、1.5mm、2.5mm、3.5mm、4.5mm、5.5mm 时
圆的面积。
3-7 求数列9,99,999…前n 项的和。
3-8 计算(1+2)+(2+3)+(3+4)+…+(n+(n+1))的值。
3-9 输入一个数n,求1+2+3+…+n+(n-1)+(n-2)+…3+2+1。例如:输入5 
时,要求输出1+2+3+4+5+4+3+2+1的值。
3-10 编程计算1!+2!+3!+…+10!的值。
3-11 编写程序,求下面数列的表达式前40项的和(结果取4位小数):1,(1/2)^4, 
(1/3)^4,…,(1/n)^4(其中,^表示幂运算)。
3-12 求下面图形中直到第几行为止,所有的*数目和为5151。 
* 
* * 
* * * 
* * * * * 
. 
3-13 编程计算a+aa+aaa+…+aa…a(n 个a)的值,n 和a 的值由键盘输入。
3-14 求1000以内所有的完全数的和(完全数是指一个数除其本身外的因子之和等于该
数。例如,28=1+2+4+7+14,因此28为完全数)。
3-15 求100以内所有同时能被3和5整除的数的和。
3-16 小猴摘桃子,第一天摘一个,以后每天摘的桃子数均是前一天的2倍多一个,求第
10天小猴子一共摘了多少个桃子。
3-17 找出100到500以内所有同时能被3、5、7整除的正整数,并用N 记录有多少个。
3-18 计算S=1+2+3+4+…+n 在累加的过程中,求当S 的值首次大于3000时的n 
值是多少。
3-19 求数列1,10,100,1000,…前n 项的和,n 由键盘输入。
3-20 已知一个数列为1,2,4,7,11,16,22,…,则数列的第n 项为多少? (提示:a2-a1=1, 
a3-a2=2,a4-a3=3,…)。
3-21 输入n 个百分制成绩,计算并输出平均成绩。要求输出结果精确到两位小数。
3-22 输入若干非0实数,以0为终止条件,统计其中正数的个数、负数的个数。
3-23 输入一行字符,统计其中的英文字母个数。提示:输入到字符\' n'时停止输入。
3-24 要求用户输入一个大于1的数,然后计算从1到这个数的累加和。
3-25 求4到200之间(包括4和200)偶数的累加和,并求这些偶数的平均值。
3-26 请编写函数fun,函数的功能是:根据以下公式计算s,计算结果作为函数值返回, 
n 通过形参传入。s=1+1/(1+2)+1/(1+2+3)+…+1/(1+2+3+…+n)。
3-27 把10个整数存入一维数组中,求这10个整数的和、最大值、最小值。
3-28 键盘输入一行字符(以回车符表示结束),将其中每个数字字符所代表的数值累加

第 
3 
章 累加法 

起来,输出结果。如输入abc235,答案输出为10 。
3-29 求e的值,根据输入的
n 
值,求前
n 
项之和。e=1+1/1!+1/2!+1/3!+…+ 

1/n!。
30 在唱歌等大奖赛评分时,一般要有若干名评委,记分规则是:去掉一个最高分和一3-
个最低分,再算平均分。设按百分制记分,请设计一个算分的程序(提示:算法的

基本思路为①输入评委人数
N 
;②逐一输入每个评委的打分,同时累加求和sum, 
并记录下最高分max和最低分min)。