1.
略
2.请补充例5.7程序,分别统计当“fabs(t)>=1e-6”和“fabs(t)>=1e-8”时执行循环体的次数。
解题思路:
设置一个整型变量count,初值为0;循环体每执行一次后,count的值加一。
(1)当”fabs(t)=1e-6“时
代码:
#include<stdio.h>
#include<math.h>
int main() {
int count = 0; //count用来记录循环体执行的次数
int sign = 1; //sign用来表示数值的符号
double pi = 0.0, n = 1.0, term = 1.0; //n代表分母,term代表当前项的值
while (fabs(term) > 1e-6) {
pi = pi + term;
n = n + 2;
sign *= -1;
term = sign / n;
count++;
}
pi *= 4;
printf("pi=%10.8f\n", pi);
printf("循环体执行了%d次\n", count);
return 0;
}
运行结果:
(2)当”fabs(t)=1e-8“时
运行结果:
3.输入两个正整数m和n,求其最大公约数和最小公倍数。
解题思路:
最大公约数:利用辗转相除法(以除数和余数反复做除法运算,当余数为 0 时,取当前算式除数为最大公约数)
例如求2344和766的最大公约数,过程如下:
2344/766=3---余46
766/46=16---余30
46/30=1---余16
30/16=1---余14
16/14=1---余2
14/2=7---余0
当余数为0时,除数为2,因此2344和766的最大公约数为2.
最小公倍数:利用公式法(两个数的乘积 等于 两个数最大公约数和最小公倍数的乘积),最小公倍数等于两个数的乘积除以两个数的最大公约数。
代码:
#include<stdio.h>
int main() {
int m, n, t, mul, ret; //mul记录两个数的乘积,ret记录余数
printf("请输入两个正整数:");
scanf_s("%d%d", &m, &n);
//保证m大于
mul= m * n;
if (m < n) {
t = m;
m = n;
n = t;
}
//
while (ret = m % n) { //若余数不为0,执行循环体内容;
m = n;
n = ret;
}
printf("最大公约数为:%d\n最小公倍数为:%d\n", n, mul / n);
return 0;
}
运行结果:
4.输入一行字符,分别统计出其中英文字母、空格、数字和其他字符的个数。
解题思路:
用while循环和 getchar()函数,每次从键盘读入一个字符,直到读入'\n'为止;读入字符后,依次判断其是否为字母、空格、数字、其他,若是,则相应记录加一。
代码:
#include<stdio.h>
int main() {
char c;
int n1=0, n2=0, n3=0, n4=0; //n1记录英文字母个数;n2记录空格个数;n3记录数字个数;n4记录其他字符个数
while ((c = getchar()) != '\n') {
if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))
n1++;
else if (c == ' ')
n2++;
else if (c >= '1' && c <= '9')
n3++;
else
n4++;
}
printf("英文字母个数为:%d\n", n1);
printf("空格个数为:%d\n", n2);
printf("空格个数为:%d\n", n3);
printf("其他字符个数为:%d\n", n4);
return 0;
}
运行结果:
5.求Sn=a+aa+aaa+...+aa...a之值,其中a是一个数字,n代表a的位数,例如:2+22+222+2222+22222(此时n=5)
解题思路:
Sn由n项相加组成,因此考虑由循环;假设a=2,n=5,分析各项组成可得如下规律:
当前项的值=前一项的值+a*10^n
代码:
#include<stdio.h>
#include<math.h>
int main() {
int a, n, cur_val=0, Sn=0; //cur_val记录当前项的值
printf("请分别输入a和n的值:");
scanf_s("%d%d", &a, &n);
for (int i = 0; i < n; i++) { //注:第n项i的值为(n-1),因此for循环中用i<n
cur_val +=a*pow(10, i);
Sn += cur_val;
}
printf("%d", Sn);
return 0;
}
运行结果:
6.求(即求1!+2!+3!+4!+...+20!)。
解题思路:
法一:类似于第五题,不再赘述。
法二:利用嵌套循环,大循环从1到20,控制加数个数;内层求解阶乘。
注:显然结果已经超过int类型所能表示的范围,因此应使用double类型。
代码:
//法一:
#include<stdio.h>
#include<math.h>
int main() {
double cur=1, total=0;
for (int i = 1; i <= 20; i++) {
cur = cur * i;
total = total + cur;
}
printf("%lf", total);
return 0;
}
//法二:
运行结果:
7.求 。
解题思路:
利用for循环,从1遍历至100,对于第一项,遍历100次后停下;对于第二项,遍历50次后停下;对于第三项,遍历10次后停下。遍历过程中,针对不同情况分别计算三项的值,最后取和。
注:由于第三项非整数,为了提高计算精度,采用双精度double类型
代码:
#include<stdio.h>
#include<math.h>
int main() {
double sum,sum1 = 0, sum2 = 0, sum3 = 0;
for (int i = 1; i <= 100; i++) {
sum1 += i;
if (i <= 50)
sum2 += i * i;
if (i <= 10)
sum3 += 1.0 / i;
}
sum = sum1 + sum2 + sum3;
printf("计算结果为:%lf\n", sum);
return 0;
}
运行结果:
8.输出所有的“水仙花数”,所谓“水仙花数”是指一个3位数,其各位数字立方和等于该数本身。例如,153是一水仙花数,因为153=1^3+5^3+3^3。
解题思路:
根据常识可得,所有的三位数范围为:100~999。
利用for循环,依次判断100~999内的每一个数是否为水仙花数,若是则输出。
代码:
#include<stdio.h>
int main() {
int a, b, c;
printf("输出所有的水仙花数:\n");
for (int i = 100; i < 1000; i++) {
a = i / 100; //a为i百位上的数字
b = i % 100 / 10; //b为i十位上的数字
c = i % 100 % 10; //c为i个位上的数字
if (i == a * a * a + b * b * b + c * c * c)
printf("%d\n", i);
}
return 0;
}
运行结果:
9.一个数如果恰好等于它的因子之和,这个数就称为“完数”。例如,6的因子为1,2,3,而6=1+2+3,因此6是“完数”。编程序找出1000之内的所有完数,并按下面格式输出其因子:6 its factors are 1,2,3
解题思路:
利用嵌套循环,外层循环变量i从1~1000;内存循环计算i的因子和,记录在sum变量中;每次内存循环结束后,判断i是否等于total,若是,则i为”完数“。
代码:
#include<stdio.h>
int main() {
int total; //total记录当前因子的和
for (int i = 1; i <= 1000; i++) {
total = 0;
for (int j = 1; j < i; j++) {
if (i % j == 0) {
total += j;
}
}
//控制输出方式
if (i == total) {
printf("%d its factors are ", i);
for (int j = 1; j < i; j++) {
if (i % j == 0)
printf("%d,", j);
}
printf("\n");
}
}
return 0;
}
运行结果:
10.有一个分数序列求出这个数列的前20项之和。
解题思路:
观察可得,后一项的分子等于前一项分子和分母的和、后一项的分母等于前一项的分子。
代码:
#include<stdio.h>
int main() {
double a = 2.0, b = 1.0, temp, total = 0;
for (int i = 1; i <= 20; i++) {
total += a/b;
temp = a; //暂存a的值
a = a + b; //把(a+b)的值赋值给a
b = temp; //把a的值赋给b
}
printf("该数列前20项的和为:%lf", total);
return 0;
}
运行结果:
11.一个球从100m高度自由落下,每次落地后反弹回原高度的一半,再落下,再反弹。求它在第10次落地时共经过多少米,第10次反弹多高。
解题思路:
反弹高度:第一次反弹高度为100/2;
第二次反弹高度为100/2/2;
第三次反弹高度为100/2/2;
......
第十次反弹高度为100/2/2/2......2;(10个2)
故设置一个变量h等于初始高度100,循环9次,每次自除2,即可得到第9次反弹的高度;最后输出h/2得到第十次的反弹高度。(循环9次是为了能和求解所经路程的循环放在一个for中,详细解释看代码注释部分)。
总路程S:第一次落地时S=100;
第二次落地时S=100+50*2;
第三次落地时S=100+50*2+25*2;
......
故设置一个变量S等于初始时高度100,循环9次,每次S=S+2*h。
注意:从第三次反弹开始,高度为小数,因此采用双精度double类型。
代码:
#include<stdio.h>
int main() {
double h=100.0, s=100.0; //h记录小球反弹高度,s记录小球共经过多少米
for (int i = 1; i < 10; i++) { //i=1时,h为第1次反弹高度、s为第2次落地时所经过的路程
h /= 2.0;
s += 2.0* h;
}
//循环结束时,i=9,h为第9次的反弹高度,s为第10次落地时所经过的路程
printf("小球在第10次落地时共经过%f米;\n第十次反弹高度为:%f米\n", s,h/2);
return 0;
}
运行结果:
12.猴子吃桃问题。猴子第一天摘下若干个桃子,当即吃了一半,还不过瘾,又多吃了一个。第2天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下的一半零一个。到第10天早上再想吃时,就只剩一个桃子了。求第1天共摘了多少个桃子?
解题思路:
贪吃猴问题可以反向求解。
第十天只剩1个桃子,则
第9天有 (1+1)*2 = 4个桃子;
第8天有(4+1)*2 = 10个桃子;
.......
设置一个变量peach记录当前桃子数量,赋初值为1,每次peach的值加1乘2得到新的peach值,循环9次后,peach的值为第一天的桃子数。
代码:
#include<stdio.h>
int main() {
int peach = 1;
for (int i = 1; i <= 9; i++) //循环9次:第十天还没吃嘞,一共吃了9天,反向求9天
peach = (peach + 1) * 2;
printf("贪吃猴第1天共摘了%d个桃子!\n", peach);
return 0;
}
运行结果:
13.用迭代法求 。求平方根的迭代公式为 ,要求前后两次求出的x的差的绝对值小于10^-5。
解题思路:
(1)设定一个x的初值为
(2)利用上述公式求出x的下一个值
(3)将带入公式右边的,求出x的下一个值
(4)如此继续下去,直到前后两次求出的x的值(和)满足以下关系:
代码:
#include<stdio.h>
#include<math.h>
int main() {
double a, x0, x1;
printf("请输入a的值:");
scanf_s("%lf", &a);
x0 = a / 2; //不妨设x的初值为a/2,也可以为其他的
x1 = (x0 + a / x0) / 2;
while (fabs(x1 - x0) >= pow(10, -5)) {
x0 = x1;
x1 = (x0 + a / x0) / 2;
}
printf("%f的平方根为:%f", a, x1);
return 0;
}
运行结果:
14.用牛顿迭代法求下面方程在1.5附近的根:
解题思路:
牛顿迭代法:任意设定一个与真实根接近的值,求出f(),过(,f())点做f(x)的切线,交x轴于点,如此下去...直到足够接近真正的根为止。
画图分析可得:
则迭代公式为:
代码:
#include<stdio.h>
#include<math.h>
int main() {
double x0, x1, f, fd; //f表示函数f(x),fd表示f(x)的导数
x1 = 1.5;
do {
x0 = x1;
f = 2 * x0 * x0 * x0 - 4 * x0 * x0 + 3 * x0 - 6;
fd = 6 * x0 * x0 - 8 * x0 + 3;
x1 = x0 - f / fd;
} while (fabs(x1-x0)>= 1e-5);
printf("该方程在1.5附近的根为:%f", x1);
return 0;
}
运行结果:
15.用二分法求下面方程在(-10,10)之间的根;
解题思路:
给定区间 [,] ,若f(x)在区间内单调变化,则可以根据f()和f()的符号来判断f(x)=0在此区间内有无实根。若f()和f()同正或同负,在无实根;若f()和f()异号,则必有一个(且只有一个)实根。当确定[,] 有一个实根后,把区间一分为二,将中点的值赋值给,再判断在哪个小区间内有实根,如此不断进行下去,直到f()无限趋近于0为止。
代码:
#include<stdio.h>
#include<math.h>
int main() {
double x1, x2, x0, f1, f2, f0; //f1表示函数f(x1),f2表示函数f(x2),f0表示函数f(x0)
x1 = -10.0;
x2 = 10.0;
do {
f1 = 2 * x1 * x1 * x1 - 4 * x1 * x1 + 3 * x1 - 6;
f2 = 2 * x2 * x2 * x2 - 4 * x2 * x2 + 3 * x2 - 6;
x0 = (x1 + x2) / 2;
f0 = 2 * x0 * x0 * x0 - 4 * x0 * x0 + 3 * x0 - 6;
if ((f1 * f0) < 0) //根在左区间
x2 = x0;
else //根在右区间
x1 = x0;
} while (fabs(f0)>=1e-5);
printf("方程在[-10,10]之间的根为%f", x0);
return 0;
}
运行结果:
16.输出以下图案:
解题思路:
将整个图像分为上四行和下三行分别处理输出:
上四行:
第0行,3个空格,1个*;
第1行,2个空格,3个*;
第2行,1个空格,5个*;
第3行,0个空格,7个*;
可以推断出:空格数=3-行数 *数=行数*2+1
下三行:
第0行,1个空格,5个*;
第1行,2个空格,3个*;
第2行,3个空格,1个*;
可以推断出:空格数=行数+1 *数=5-2*行数
代码:
#include<stdio.h>
int main() {
for (int i = 0; i <= 3; i++) { //控制上面4行
for(int j = 0; j <= 2-i; j++) //控制空格
printf(" ");
for (int k = 0; k <= 2*i; k++) //控制*
printf("*");
printf("\n");
}
for (int i = 0; i <= 2; i++) {
for (int j = 0; j <= i; j++)
printf(" ");
for (int k = 0;k <= 4-(2*i); k++)
printf("*");
printf("\n");
}
return 0;
}
运行结果:
17.两个乒乓球队进行比赛,各处出人。甲队为A,B,C 3人,乙队为X,Y,Z 3人。以抽签决定比赛名单。有人向队员打听比赛的名单,A说他不和X比,C说他不和X,Z比,请编程找出3对赛手名单。
解题思路:
假设A与i比赛,B与j比赛,C与k比赛。i,j,k 分别是X、Y、Z之一,且i,j,k互不相等。
外循环使i由 'X' 变到 'Z' ,中循环使j由 'X' 变到 'Z'(i、j不应相等)。对每一组i、j的值,找到复合条件的k值。k同样也可能是 'X'、'Y'、'Z'之一,但k也不应与i、j相等。在i!=j!=k的条件下,再把i!= 'X'和k!='X' 和k!='Z'的i、j、k输出即可。
代码:
#include<stdio.h>
int main() {
char i, j, k; //假设A的对手是i,B的对手是j,C的对手是K
for(i='X';i<='Z';i++)
for (j = 'X'; j <= 'Z'; j++)
if (i != j) {
for (k = 'X'; k < 'Z'; k++) {
if (k != i && k != j) {
if (i != 'X' && k != 'X' && k != 'Z')
printf("A-%c,B-%c,C-%c", i, j, k);
}
}
}
return 0;
}
运行结果:
更多章节答案,看我主页哦。