- OS: Mac Catalina 10.15.4
- Hardware: Intel Core i9/16G 2667MHz DDR4
- 编译器版本:Mac Xcode 11.6
第06章 C控制语句:循环
目录
例题1 依据用户输入的整数求和 Page 137
/* summing.c -- 根据用户输入的整数求和 */
#include <stdio.h>
int main(void)
{
long num;
long sum = 0L; /* 把sum初始化为0 */
int status;
printf("Please enter an integer to be summed ");
printf("(q to quit): ");
status = scanf("%ld", &num);
while (status == 1) /* ==的意思是“等于” */
{
sum = sum + num;
printf("Please enter next integer (q to quit): ");
status = scanf("%ld", &num);
}
printf("Those integers sum to %ld.\n", sum);
return 0;
}
程序输出结果:
例题2 何时退出循环 Page 141
/* when.c -- 何时退出循环 */
#include <stdio.h>
int main(void)
{
int n = 5;
while (n < 7)
{
printf("n = %d\n", n);
n++;
printf("Now n = %d\n", n);
}
printf("The loop has finished.\n");
return 0;
}
程序输出结果:
例题3 无限循环 Page 141
/* while1.c -- 注意花括号的使用 */
/* 糟糕的代码创建了一个无限循环 */
#include <stdio.h>
int main(void)
{
int n = 0;
while (n < 3)
printf("n is %d\n", n);
n++;
printf("That's all this program does\n");
return 0;
}
程序输出:
注意:
- 虽然n++写在了printf后面,但是没有使用花括号将其包含在while语句范围
例题4 while循环分号的错误放置 Page 142
/* while2.c -- 注意分号的位置 */
#include <stdio.h>
int main(void)
{
int n = 0;
while (n++ < 3);
printf("n is %d\n", n);
printf("That's all this program does.\n");
return 0;
}
程序输出:
注意:
- while(n++ < 3)后面跟了;号,表示是一个空循环,其后的printf("n is %d\n", n)并不在循环内部。
- 如果在程序上的确需要空循环,则使用分号(;)单独一行,并加以注释为何要空循环。
例题5 浮点数的比较 page 144
// cmpflt.c -- 浮点数的比较
#include <stdio.h>
#include <math.h>
int main(void)
{
const double ANSWER = 3.14159;
double response;
printf("What is the value of pi?\n");
scanf("%lf", &response);
while (fabs(response - ANSWER) > 0.0001)
{
printf("Try again!\n");
scanf("%lf", &response);
}
printf("Close enought!\n");
return 0;
}
程序输出结果:
注意:
- 浮点数比较,避免使用==,>=,<=,而使用>或者<
例题6 真值,假值 Page 144
/* t_and_f.c -- C中的真和假的值 */
#include <stdio.h>
int main(void)
{
int true_val, false_val;
true_val = (10 > 2); // 关系为真的值
false_val = (10 == 2); // 关系为假的值
printf("true = %d; false = %d\n", true_val, false_val);
return 0;
}
程序输出结果:
注意:
- true!=0
- false=0
例题7 表示真值的其它方法 Page 145
// truth.c -- 哪些值为真
#include <stdio.h>
int main(void)
{
int n = 3;
while(n)
printf("%2d is true\n", n--);
printf("%2d is false\n", n);
n = -3;
while(n)
printf("%2d is true\n", n++);
printf("%2d is false\n", n);
return 0;
}
程序输出结果:
注意:
- true!=0
- false=0
例题8 逻辑判断=会导致的错误 page 146
// trouble.c -- 误用=会导致无限循环
#include <stdio.h>
int main(void)
{
long num;
long sum = 0L;
int status;
printf("Please enter an integer to be summed ");
printf("(q to quit): ");
status = scanf("%ld", &num);
while (status = 1)
{
sum = sum + num;
printf("Please enter next integer (q to quit): ");
status = scanf("%ld", &num);
}
printf("Those integers sum to %ld.\n", sum);
return 0;
}
程序输出结果:
注意:
- scanf读入一个失败的数值,会将这个值返回原来的地方,当再次读入时有发生了错误。进入了无限循环的错误机制。
xcode有代码检错机制,会提示用户的代码存在错误。如下图:
例题9 _Bool类型的使用 Page 148
// boolean.c -- 使用_Bool类型的便利variable
#include <stdio.h>
int main(void)
{
long num;
long sum = 0L;
_Bool input_is_good;
printf("Please enter an integer to be summed ");
printf("(q to quit): ");
input_is_good = (scanf("%ld", &num) == 1);
while (input_is_good)
{
sum = sum + num;
printf("Please enter next integer (q to quit): ");
input_is_good = (scanf("%ld", &num) == 1);
}
printf("Those integers sum to %ld.\n", sum);
return 0;
}
程序输出:
注意:
- _Bool 为C99标准
- 如果引用<stdbool.h>则可以使用bool代替_Bool,并且可使用true和false,这样可以和c++兼容
- 如果编译器不支持_Bool,则使用int代替
例题10 指定循环次数的while循环 Page 150
// sweetie1.c -- 一个计数循环
#include <stdio.h>
int main(void)
{
const int NUMBER = 22;
int count = 1; // 初始化
while (count <= NUMBER) // 测试
{
printf("Be my Valentine!\n"); // 行为
count++; // 更新计数器
}
return 0;
}
输出结果:
注意:
- 类似这种循环可以使用for循环代替
例题11 for循环 Page 151
// sweetie2.c -- 使用for循环的计数循环
#include <stdio.h>
int main(void)
{
const int NUMBER = 22;
int count;
for (count = 1; count <= NUMBER; count++)
printf("Be my Valentine!\n");
return 0;
}
程序输出结果 :
注意:
- 如果循环变量在循环外申明且for语句有初始化循环变量,则无需对循环外的循环变量初始化
例题12 for 循环求x^3 Page 151
#include <stdio.h>
int main(void)
{
int num;
printf(" n n cubed\n");
for (num = 1; num <= 6; num++)
printf("%5d %5d\n", num, num * num * num);
return 0;
}
程序输出结果:
例题13 逗号运算符 Page 156
// postage.c -- 一类邮资
#include <stdio.h>
int main(void)
{
const int FIRST_OZ = 46; // 2013年邮资
const int NEXT_OZ = 20; // 2013年邮资
int ounces, cost;
printf(" ounces cost\n");
for (ounces = 1, cost = FIRST_OZ; ounces <= 16; ounces++, cost += NEXT_OZ)
printf("%5d $%4.2f\n", ounces, cost / 100.0);
return 0;
}
程序输出结果:
例题14 使用for做数列计算 Page 158
/* zeno.c -- 求序列的和 */
#include <stdio.h>
int main(void)
{
int t_ct; // 项计数
double time, power_of_2;
int limit;
printf("Enter the number of terms you want: ");
scanf("%d", &limit);
for (time = 0, power_of_2 = 1, t_ct = 1; t_ct <= limit;
t_ct++, power_of_2 *= 2.0)
{
time += 1.0 / power_of_2;
printf("time = %f when terms = %d.\n", time, t_ct);
}
return 0;
}
输出结果:
注意:
- 在做数学计算的程序中,因考虑数学方法化简后,再写程序
例题15 do...while 循环 Page 159
/* do_while.c -- 出口条件循环 */
#include <stdio.h>
int main(void)
{
const int secret_code = 13;
int code_entered;
do
{
printf("To enter the triskaidekaphobia therapy club,\n");
printf("please enter the secret code number: ");
scanf("%d", &code_entered);
}while (code_entered != secret_code);
printf("Congratulations! You are cured!\n");
return 0;
}
程序输出结果:
注意:
- do...while循环至少执行一次
例题16 使用while循环重写例题15 Page 160
/* entry.c -- 出口条件循环 */
#include <stdio.h>
int main(void)
{
const int secret_code = 13;
int code_entred;
printf("To enter the triskaidekaphobia therapy club,\n");
printf("please enter the secret code number: ");
scanf("%d", &code_entred);
while (code_entred != secret_code)
{
printf("To enter the triskaidekaphobia therapy club,\n");
printf("please enter the secret code number: ");
scanf("%d", &code_entred);
}
printf("Congratulations! Your are cured!\n");
return 0;
}
程序输出结果:
注意:
- 依据实际情况,合理选择while循环,for循环,do...while循环
例题17 使用嵌套循环 Page 162
/* rows1.c -- 使用嵌套循环 */
#include <stdio.h>
#define ROWS 6
#define CHARS 10
int main(void)
{
int row;
char ch;
for (row = 0; row < ROWS; row++)
{
for(ch = 'A'; ch < ('A' + CHARS); ch++)
printf("%c", ch);
printf("\n");
}
return 0;
}
程序输出结果
例题18 依赖外部循环的嵌套循环 Page 163
// rows2.c -- 依赖外部循环的嵌套循环
#include <stdio.h>
int main(void)
{
const int ROWS = 6;
const int CHARS = 6;
int row;
char ch;
for (row = 0; row < ROWS; row++)
{
for (ch = ('A' + row); ch < ('A' + CHARS); ch++)
printf("%c", ch);
printf("\n");
}
return 0;
}
程序输出结果:
例题19 使用循环处理数组 Page 165
// scores_in.c -- 使用循环处理数组
#include <stdio.h>
#define SIZE 10
#define PAR 72
int main(void)
{
int index, score[SIZE];
int sum = 0;
float average;
printf("Enter %d golf scores:\n", SIZE);
for (index = 0; index < SIZE; index++)
scanf("%d", &score[index]); // 读取10个分数
printf("The scores read in are as follows:\n");
for (index = 0; index < SIZE; index++)
printf("%5d", score[index]); //验证输入
printf("\n");
for (index = 0; index < SIZE; index++)
sum += score[index]; //求总分
average = (float)sum / SIZE; //求平均分
printf("Sum of scores = %d, average = %.2f\n", sum, average);
printf("That's a handicap of %.0f.\n", average - PAR); // 求差点(它是平均分与标准分的差值)
return 0;
}
程序输出结果:
注意:
- 虽然输入了11个数字,但是只接受了10个数字,因为只使用10次循环读入数字
- 读入给数组的数字应使用&score[index]
例题20 计算数的整数幂 Page 167
// power.c --计算数的整数次幂
#include <stdio.h>
double power(double n, int p); // ANSI函数原型
int main(void)
{
double x, xpow;
int exp;
printf("Enter a number and the positive integer power");
printf(" to which\nthe number will be raised. Enter q");
printf(" to quit.\n");
while (scanf("%lf%d", &x, &exp) == 2)
{
xpow = power(x, exp); //函数调用
printf("%.3g to the power %d is %.5g\n", x, exp, xpow);
printf("Enter next pair of numbers or q to quit.\n");
}
printf("Hope you enjoyed this power trip -- bye!\n");
return 0;
}
double power(double n, int p) // 函数定义
{
double power = 1;
int i;
for (i = 1; i <= p; i++)
power *= n;
return power; //返回pow的值
}
程序运行结果:
注意:
- scanf("%lf", &x)读入的数据存储为double类型
- printf("%.3g", x)输出小数位保留3位的double类型
编程练习
习题1
编写一个程序,创建一个包含26个元素的数组,并在其中存储26个小写字母。然后打印数组的所有内容
#include <stdio.h>
#define SIZE 26
#define CHAR 'a'
void init_array(char* array);
void print_array(char* array);
int main(void)
{
char array[SIZE];
printf("array size 26, init array start with 'a'.\n");
init_array(array);
printf("now start print array.\n");
print_array(array);
return 0;
}
void init_array(char* array)
{
int index;
for (index = 0; index < SIZE; index++)
array[index] = CHAR + index;
}
void print_array(char* array)
{
int index;
for (index = 0; index < SIZE; index++)
printf("%2c", array[index]);
printf("\n");
}
程序输出结果:
习题2
使用嵌套循环,按下面的格式打印字符:
#include <stdio.h>
#define ROW 5
int main(void)
{
int row, count;
for (row = 0; row < ROW; row++)
{
for(count = 0; count <= row; count++)
printf("$");
printf("\n");
}
return 0;
}
程序输出结果
习题3
使用嵌套循环,按下面的格式打印字母:
#include <stdio.h>
#define ROW 6
int main(void)
{
int row, ch;
for (row = 0; row < ROW; row++)
{
for (ch = 0; ch <= row; ch++)
printf("%c", 'F' - ch);
printf("\n");
}
return 0;
}
程序输出结果:
习题4
使用嵌套循环,按下面的格式打印字母:
#include <stdio.h>
#define ROW 6
int main(void)
{
int row, letter;
char ch = 'A';
for (row = 0; row < ROW; row++)
{
for (letter = 0; letter <= row; letter++)
printf("%c", ch + letter);
ch += letter;
printf("\n");
}
return 0;
}
程序输出结果:
习题5
编写一个程序,提示用户输入大写字母。使用嵌套循环以下面金字塔型的格式打印字母:
打印这样的图形,要根据用户输入的字母来决定。例如,上面的图形是在用户输入E后的打印结果。
提示:如果外层循环处理行,每行使用3个内层循环,分别处理空格、以升序打印字母、以降序打印字母。
#include <stdio.h>
int main(void)
{
const char A = 'A';
const char Z = 'Z';
int i, j;
char ch; //输入的字母
printf("Enter an alphabet(A~Z): ");
scanf("%c", &ch);
if(ch >= A && ch <= Z)
{
//控制行
for(i = A; i <= ch; i++)
{
//行前空格
for(j = ch - i; j > 0; j--)
printf(" ");
//开始输出中间及左边的字母
for(j = A; j <= i; j++)
printf("%c", j);
//开始输出中间右边的字母
for(j -= 2; j >= A; j--) //j -= 2表示回到输出字符的前一个字符
printf("%c", j);
printf("\n");
}
} else
printf("Must enter alphabet(A~Z), program exit.\n");
return 0;
}
程序输出结果:
习题6
编写一个程序打印一个表格,每一行打印一个整数、该数的平方、该数的立方。
要求用户输入表格的上下限。使用一个for循环
#include <stdio.h>
int main(void)
{
int start, end;
printf("输入表格上下限制整数(步长=1):");
scanf("%d%d", &start, &end);
printf("%4s|%6s|%6s\n", "x", "x^2", "x^3");
printf("-----------------------------\n");
for(; start <= end; start++)
{
printf("%4d|%6d|%6d\n", start, start * start, start * start * start);
}
printf("-----------------------------\n");
return 0;
}
程序输出结果 :
习题7
编写一个程序把一个单词读入一个字符数组中,然后倒序打印这个单词。
提示:strlen()函数(第4章介绍过)可用于计算数组最后一个字符的下标;
#include <stdio.h>
#include <string.h>
int main(void)
{
char ch_array[181];
size_t index;
printf("输入一个单词,按回车结束输入: ");
scanf("%s", ch_array);
printf("倒序打印单词: ");
/*
size_t index = 0
当index - 1时,index = 18446744073709551615
将导致无限循环,解决方案是:使用循环控制
*/
for(index = strlen(ch_array); index > 0; index--)
{
printf("%c", ch_array[index - 1]);
}
printf("\n");
return 0;
}
程序输出结果:
注意:
- 1. 读入字符串到字符数组scanf()不需要地址符号 &
- 2. strlen()使用头文件<string.h>
- 3. size_t类型在0时,当减1时,值会变成:18446744073709551615,因为它是无符号型,所以在循环控制时不能使用<0来做检查
习题8
编写一个程序,要求用户输入两个浮点数,并打印两数之差除以两数之积的结果。在用户输入非数字之前,
程序应循环处理用户输入的每对值
#include <stdio.h>
#include <math.h>
#define EPSINON 0.000001 //计算误差不能超过0.000001
int main(void)
{
float a, b;
int count;
char getBuff = '\0';
printf("输入两个浮点数: ");
count = scanf("%f%f", &a, &b);
//必须有两个数被正确读入,两个数相乘不能为0
while(count != 2 || abs(a * b - 0.0) <= EPSINON)
{
if(count != 2)
printf("输入的数据无效,请输入两个浮点数:");
else
printf("分母不能为0.计算失败,请输入两个浮点数:");
//读取失败后,清除scan缓冲区
while((getBuff=getchar()!='\n' && getBuff != EOF));
//重新输入
count = scanf("%f%f", &a, &b);
}
printf("两数之差除以两数之积: (%f - %f) / (%f * %f) = %f\n",
a, b, a, b, (a - b) / (a * b));
return 0;
}
程序输出结果:
注意:
- 1. scanf()读入失败后,驻留在缓存区的字符要被清除,否则下次读入依旧错误
- 2. float类型的读入或者计算会有误差,比如读入3.2但是数据储存为3.200005,不能直接使用浮点数进行比较,需使用误差范围控制。这里使用EPSINON=0.000001控制
- 3. 计算这个例题时要控制分母不能为0,如果为0,将导致计算结果为无穷大(inf)
习题9
修改练习8,使用一个函数返回计算结果
#include <stdio.h>
#include <math.h>
#define EPSINON 0.000001 //计算误差不能超过0.000001
float cal(float a, float b);
int main(void)
{
float a, b;
int count;
char getBuff = '\0';
printf("输入两个浮点数: ");
count = scanf("%f%f", &a, &b);
//必须有两个数被正确读入,两个数相乘不能为0
while(count != 2 || abs(a * b - 0.0) <= EPSINON)
{
if(count != 2)
printf("输入的数据无效,请输入两个浮点数:");
else
printf("分母不能为0.计算失败,请输入两个浮点数:");
//读取失败后,清除scan缓冲区
while((getBuff=getchar()!='\n' && getBuff != EOF));
//重新输入
count = scanf("%f%f", &a, &b);
}
printf("两数之差除以两数之积: (%f - %f) / (%f * %f) = %f\n",
a, b, a, b, cal(a, b));
return 0;
}
float cal(float a, float b)
{
return (a - b) / (a * b);
}
程序输出结果:
习题10
10. 编写一个程序,要求用户输入一个上限整数和下限整数,计算从上限到下限范围内所有整数的平方和,并显示计算结果。然后程序继续提示用户输入上限和下限整数,并显示结果,直到用户输入的上限整数等于或小于下限整数为止。程序的运行示例如下:
Enter lower and upper integer limits: 5 9
The sums of the squares from 25 to 81 is 255
Enter next set of limits: 3 25
The sums of the squares from 9 to 625 is 5520
Enter next set of limits: 5 5
Done
#include <stdio.h>
unsigned int sums(int a, int b);
int main(void)
{
int a, b;
do
{
printf("Enter lower and upper integer limits: ");
scanf("%d%d", &a, &b);
if(a >= b) break;
printf("The sums of the squares from %d to %d is %u\n", a, b, sums(a, b));
}while(1);
printf("Done\n");
return 0;
}
unsigned int sums(int a, int b)
{
int i = a;
unsigned int sums = 0;
for(; i <= b; i++)
{
sums += i * i;
}
return sums;
}
程序输出结果 :
习题11
编写一个程序,在数组中输入8个整数,然后按倒序打印这8个整数
#include <stdio.h>
#define LENGTH 8
int main(void)
{
int array[LENGTH], index;
printf("输入8个整数: ");
for(index = 0; index < LENGTH; index++)
scanf("%d", &array[index]);
//倒序输出
printf("倒序输出:");
for(index = LENGTH - 1; index >= 0; index--)
printf(" %d ", array[index]);
printf("\n");
return 0;
}
程序输出结果:
习题12
考虑下面两个无限序列
1.0 + 1.0/2.0 + 1.0/3.0 + 1.0/4.0 + ...
1.0 - 1.0/2.0 + 1.0/3.0 - 1.0/4.0 + ...
编写一个程序计算这两个无限序列的总和,直到达到某次数。提示:奇数个数-1 相乘得-1,偶数个数-1相乘得1。让用户交互地输入指定的次数,当用户输入0或负值时结束输入。查看运行100项、1000项、10000项后的总和,是否发现每个序列都收敛于某值
/*
对于两个序列求和,可使用简化方法,将上下两个序列上下相加得:
2 + 2(1.0/3.0) + 2 (1.0/5.0) + ...
=2(1 + 1.0/3.0 + 1.0 / 5.0 + ...)
可知,只需要计算奇数项,偶数项全部为0,将所有奇数项相加后乘以2
*/
#include <stdio.h>
double cal_sums(unsigned int count);
double cal_1(unsigned int count);
double cal_2(unsigned int count);
int main(void)
{
int count = 0;
printf("输入项: ");
while(scanf("%d", &count) == 1)
{
if(count <= 0)break;
printf("序列1 = %.12lf\n", cal_1(count));
printf("序列2 = %.12lf\n", cal_2(count));
printf("序列总和 = %.12lf\n输入项: ", cal_sums(count));
}
printf("Done\n");
return 0;
}
//计算序列1
double cal_1(unsigned int count)
{
double sums = 0;
unsigned int i = 1;
for(; i <= count; i++)
sums += 1.0 / i;
return sums;
}
//计算序列2
double cal_2(unsigned int count)
{
unsigned int i = 1;
double sums = 0;
for(; i <= count; i++)
{
if(i % 2 == 0)
sums += -1.0 / i;
else
sums += 1.0 / i;
}
return sums;
}
double cal_sums(unsigned int count)
{
unsigned int i = 1;
double sums = 0;
//如果是偶数,则总项-1,因为偶数项相加得0
if(count % 2 == 0) count--;
for(; i <= count; i += 2) //只计算奇数项
{
sums += 1.0 / i;
}
sums *= 2;
return sums;
}
程序输出结果:
对比数学软件计算结果(Mathematica)
注意:
- 1. 对于数值计算的应优先考虑数学上的优化,使用数学方法化简后再编写程序。对于上题的例子求和是,将两个序列上下相加后可简化操作,具体见注释说明
- 2. 对于数学计算的,应该使用数学软件进行检查是否计算正确
- 3. 对于舍入误差或者丢弃进度快速计算的参考数值计算相关书籍,比如微分中值定理
习题13
编写一个程序,创建一个包含8个元素的int类型数组,分别把数组元素设置为2的前8次幂。使用for循环设置数组元素的值,使用do while循环显示数组元素的值
#include <stdio.h>
#include <math.h>
#define LENGTH 8
int main(void)
{
int array[LENGTH], index = 0;
printf("数组初始化...\n");
for(; index < LENGTH; index++)
array[index] = 0;
printf("设置数组....");
for(index = 0; index < LENGTH; index++)
array[index] = pow(2, index);
printf("设置完毕.\n");
printf("输出数组: ");
index = 0;
do
{
printf(" %d", array[index++]);
}while(index < LENGTH);
printf("\nDone.\n");
return 0;
}
程序输出结果:
习题14
编写一个程序,创建两个包含8个元素的double类型数组,使用循环提示用户为第一个数组输入8个值。第二个数组元素的值设置为第一个数组对应元素的累积之和。例如第二个数组的第4个元素的值是第一个数组前4个元素之和,第二个数组的第5个元素的值是第一个数组前5个元素之和(用嵌套循环可以完成,但是利用第二个数组的第5个元素是第二个元素的前4个元素与第一个数组的第5个元素之和,只用一个循环就能完成任务,不需要使用嵌套循环)。最后使用循环显示两个数组的内容,第一个数组显示成一行,第二个数组显示在第一个数组的下一行,而且每个元素都与第一个数组各元素相对应.
#include <stdio.h>
void print(double *p, int size);
int main(void)
{
const int LENGTH = 8;
int index = 0;
double array1[LENGTH], array2[LENGTH];
printf("读入8个double类型数值:");
for(; index < LENGTH; index++)
scanf("%lf", &array1[index]);
printf("开始计算...");
for(index = 0; index < LENGTH; index++)
{
if(index == 0)
array2[index] = array1[index];
else
array2[index] = array2[index - 1] + array1[index];
}
printf("计算完毕.\n开始输出...\n");
printf("第一个数组:");
print(array1, LENGTH);
printf("\n第二个数组:");
print(array2, LENGTH);
printf("\nDone.\n");
return 0;
}
void print(double *p, int size)
{
int index = 0;
for(; index < size; index++)
printf(" %.5lf\t", p[index]);
}
程序输出结果:
习题15
编写一个程序,读取一行输入,然后把输入的内容倒序打印出来。可以把输入存储在char类型的数组中,假设每行字符不超过255。回忆一下,根据%c转换说明,scanf()函数一次只能从输入中读取一个字符,而且在用户按下Enter键时scanf()函数会生成一个换行字符(\n)
#include <stdio.h>
#include <string.h>
int main(void)
{
const int LENGTH = 256;
size_t i = 0;
char array[LENGTH];
printf("输入一行文本(不超过255个字符):\n");
scanf("%[^\n]", array); //读入整行字符串,直到遇到回车换行截止
printf("输入的字符串总长度:%zu\n", strlen(array));
printf("开始倒序输出:");
for(i = strlen(array); i > 0; i--)
{
printf("%c", array[i - 1]);
}
printf("\nDone.\n");
return 0;
}
程序输出结果:
在Debug状态下,可以看到在字符数组array[4]是'\0',如下图。未在windows环境下测试
习题16
Daphne以10%的单利息投资了100美元(也就是说,每年投资获利相当于原始投资的10%)。Deirdre以5%的复合利息投资了100美元(也就是说,利息是当前余额的5%,包括之前的利息)。编写一个程序,计算需要多少年Dirdre的投资才会超过Daphne,并显示那时两人的投资额
#include <stdio.h>
void printLine(void);
int main(void)
{
//初始投资成本
float initDaphne = 100.0, initDeirdre = 100.0;
float interestDaphne = 0.0, interestDeirdre = 0.0;
//单利息10%,复利息5%
const float SINGLE_INTERSET = 0.1, COMPOUND_INTERSET = 0.05;
//累计投资资本
float investDaphne = initDaphne, investDeirdre = initDeirdre;
//年
short int year = 0;
printf("Daphne\t\t\t\t单利\t\t利率:%.2f%%\t|Deirdre\t\t\t复利\t\t利率:%.2f%%\n",
SINGLE_INTERSET * 100,COMPOUND_INTERSET * 100);
printLine();
printf("年\t投资额\t\t利息\t\t\t余额\t\t\t|投资额\t\t利息\t\t\t余额\n");
printLine();
do
{
year++;
//Daphne的利息 = 原始投资 * 10%
interestDaphne = initDaphne * SINGLE_INTERSET;
printf("%d\t%.4f\t%.4f\t", year,
investDaphne, interestDaphne);
//Daphne的投资额 = 投资额+利息
investDaphne += interestDaphne;
printf("\t%.4f\t",investDaphne);
//Deirdre的利息 = 累计投资额 * 5%
interestDeirdre = investDeirdre * COMPOUND_INTERSET;
printf("|%.4f\t%.4f", investDeirdre, interestDeirdre);
//Deirdre的投资额 = 累计投资额+利息
investDeirdre += interestDeirdre;
printf("\t\t%.4f\n",investDeirdre);
}while(investDeirdre <= investDaphne);
printLine();
return 0;
}
void printLine(void)
{
printf("--------------------------------------");
printf("--------------------------------------\n");
}
程序运行结果:
注意:
1. 复利计算方式有专用数学公式,上面的习题没有使用数学公式,数学公式如下:
其中A为总收入,P为投资额,r为复利,k为每年支付的次数,t为年数
参考文献:
《Intermediate Algebra》9th Edition. International Edition. By Gustafson、Karr、Massey. Page 627
习题17
Chuckie Lucky赢得了100万美元(税后),他把奖金存入年利率8%的账户。在每年的最后一天,Chuckie取出10万美元。便携一个程序,计算多少年后Chuckie会取完账户的钱?
#include <stdio.h>
void printLine(void);
int main(void)
{
//初始投资成本
float init = 1000000;
float interest = 0.08;
//复利息8%
const float COMPOUND_INTERSET = 0.08;
//每年年末固定取走一笔10万的金额
const float WITHDRAW_MONDY = 100000;
//累计投资资本
float invest = init;
//年
short int year = 0;
printf("Chuckie Lucky\t\t\t复利\t\t利率:%.2f%%\n",
COMPOUND_INTERSET * 100);
printLine();
printf("年\t投资额\t\t\t利息\t\t\t取款金额\t\t余额\n");
printLine();
do
{
year++;
//利息 = 累计投资额 * 10%
interest = invest * COMPOUND_INTERSET;
printf("%d\t%12.4f\t%10.4f\t", year, invest, interest);
//投资额 = 投资额+利息
invest += interest;
//如果足够扣减10万,则扣减10万,否则扣减余额
if(invest - WITHDRAW_MONDY >= 0)
{
//取款金额
printf("%6.0f\t", WITHDRAW_MONDY);
//投资额 = 投资额+利息-取款金额
invest -= WITHDRAW_MONDY;
}
else
{
//取款金额
printf("%6.0f\t", invest);
//投资额 = 投资额+利息-取款金额
invest = 0;
}
printf("\t%11.4f\n",invest);
}while(invest > 0);
printLine();
return 0;
}
void printLine(void)
{
printf("------------------------------");
printf("------------------------------\n");
}
程序输出结果:
习题18
Rabnud博士加入了一个社交圈。起初他有5个朋友。他注意到他的朋友数量以下面的方式增长。第1周少了1个朋友,剩下的朋友数量翻倍;第2周少了2个朋友,剩下的朋友数量翻倍。一般而言,第N周少了N个朋友,剩下的朋友数量翻倍。编写一个程序,计算并显示Rabnud博士每周的朋友数量。该程序一直运行,知道超过邓巴数(Dunbar's number)。邓巴数是粗略估算一个人在社交圈中有稳定关系的成员的最大值,该值大约是150
#include <stdio.h>
void printline(void);
int main(void)
{
//起初朋友数
unsigned int init = 5;
//结余朋友数
unsigned int sums = init;
//周数
unsigned short weeks = 1;
//少了的人数
unsigned short lost_friend = weeks;
//余下人数
unsigned short remain_friend = 0;
//Dunbar's number
const unsigned int DUNBARS_NUMBER = 150;
printf("Rabnud 博士\n");
printline();
printf("第N周\t|起初值\t少了N个朋友\t余下朋友数\t余下朋友翻倍数\n");
printline();
do
{
//第N周
printf("%4d\t", weeks);
//起初值
printf("|%4d\t", sums);
//少了的人数
lost_friend = weeks;
//余下人数
remain_friend = sums - lost_friend;
//余下朋友翻倍数
sums = remain_friend * 2;
printf("%4d\t\t%4d\t\t%4d\n", lost_friend,
remain_friend, sums);
weeks++;
}while(sums <= DUNBARS_NUMBER);
printline();
return 0;
}
void printline(void)
{
printf("------------------");
printf("------------------------------------\n");
}
程序输出结果: