求和
上述表达式的起点1和终点n比较明确,使用for循环更合适。
#include <stdio.h>
int main()
{
int a = 1;
int n;
double sum;
scanf("%d",&n);
for(a;a <= n;a++)
{
sum += 1.0/a;
}
printf("f(%d)=%f",n,sum);
return 0;
}
3
f(3)=1.833333
--------------------------------
Process exited after 1.677 seconds with return value 0
在除号两边放一个浮点数,会把另一个数字也变成浮点数。
#include <stdio.h>
int main()
{
int a = 1;
int n;
double sum;
int sign = 1;
scanf("%d",&n);
for(a;a <= n;a++)
{
sum += sign * 1.0/a;
sign = -sign;
}
printf("f(%d)=%f",n,sum);
return 0;
}
3
f(3)=0.833333
--------------------------------
Process exited after 1.119 seconds with return value 0
上述程序可以将变量sign定义为double类型并赋值1.0,在12行中将分子的1去掉,变为sign / a。
最大公约数
输入两个数字求最大公约数
- 枚举:
如果两个数都能被同一个数a整除,这个数字就是两个数的公约数记为i,数字a每次加1,再用两个数整除,如果余数为0,就赋值给i,直到数字a和两个数中的某一个相等,此时i
的值为两个数字的最大公约数。
#include <stdio.h>
int main()
{
int a,b;
scanf("%d %d",&a,&b);
int min;
if(a < b){
min = a;
}else{
min = b;
}
int i;
int ret;
for(i = 1;i < min;i++){
if (a % i == 0){
if (b % i == 0){
ret = i;
}
}
}
printf("%d和%d的最大公约数是%d",a,b,ret);
return 0;
}
12 16 12和16的最大公约数是4
Process exited after 3.57 seconds with return value 0
上述程序的循环体,i为公约数,从1开始(两个质数的最大公约数为1),依次递增。debug for循环,发现程序在满足循环条件时执行16行第一个if循环语句,如果16行if语句成立,执行17行的if语句,如果不成立,回到for循环中继续执行for循环的动作并进入下一轮循环。
2.辗转相除法
**算法:求a和b的最大公约数,a除以b,余数记为t,然后使得a=b,b=t,继续计算a除以b,t为余数,a=b,b=t,直到b=0,计算结束,a的值为最大公约数。**
#include <stdio.h>
int main() { int a,b; int t = 0; scanf("%d %d",&a,&b); for(t = 0;b != 0;){ t = a % b; a = b; b = t; } printf("最大公约数为%d",a); return 0; }
12 18 最大公约数为6
Process exited after 4.289 seconds with return value 0
::: tip
while循环可以和for循环等价互换,上述的for循环可以使用如下程序替代:
while(b != 0){ t = a % b; a = b; b = t; }
:::
------------------------------------
###### 整数分解
1.正序分解整数
要求:输入非负整数,正序输出每一位数字,中间加空格,末尾不加空格。
#include <stdio.h>
int main()
{
int a;
scanf("%d",&a);
int d;
while(a > 0){
d = a % 10;
printf("%d ",d);
a /= 10;
}
return 0;
}
15243 3 4 2 5 1
Process exited after 2.629 seconds with return value 0
部分编译器会输出如下信息:
15243 3 4 2 5 1 Program exited with status 0
如上图所示,输出结果1后面有空格,可以做如下的改动:
#include <stdio.h>
int main()
{
int a;
scanf("%d",&a);
int d;
while(a > 0){
d = a % 10;
printf("%d",d);
a /= 10;
if(a >= 0){
printf(" ",d);
}
}
printf("\n");
return 0;
}
265563 3 6 5 5 6 2Program exited with status 0
为方便观察输出最后一个数字后是否有空格,程序退出提示在输出结果一行,可以在return那一行之前加上“**printf("\n");**”
2.逆序分解整数
算法:逆序分解整数可以在正序的基础上,先执行一轮循环将整数倒过来写,然后再正序输出。该循环中先设逆序后的数字为t,每次提取出正序整数的最后一位记为d,然后使得t=t*10+d,最后使用a/=10丢掉a的最后一位数字。
#include <stdio.h>
int main()
{
int a;
scanf("%d",&a);
int d;
int t = 0;
do{
d = a % 10;
t = t *10 + d;
a /= 10;
}while(a > 0);
printf("%d\n",t);
a = t;
while(a > 0){
d = a % 10;
printf("%d",d);
if(a >= 10){
printf(" ",d);
}
a /= 10;
}
printf("\n");
return 0;
}
152634 436251 1 5 2 6 3 4
Process exited after 3.839 seconds with return value 0
在第一个do-while循环后,a的值已经为0,需要将逆序后的t重新赋值给a才可以使得a继续参与下面的while循环(也可以使用t的值代替逆序前的a参与循环)。
::: tip
do-while循环和while循环都可以使用。
**在选择循环类型时,如果循环有固定次数,使用for循环,如果循环必须进行一次,使用do while循环,其他情况都用while循环。**
:::
**上述程序只适用于末尾不为0的情况。**
#include <stdio.h>
int main()
{
/*
13524 / 10000 -> 1
13524 % 10000 -> 3524
10000 / 10 -> 1000
3524 / 1000 -> 3
3524 % 1000 -> 524
1000 / 10 -> 100
524 / 100 -> 5
524 % 100 -> 24
100 / 10 -> 10
24 / 10 -> 2
24 % 10 -> 4
10 / 10 -> 1
4 / 1 -> 4
4 % 1 -> 0
1 / 10 -> 0
*/
int mask = 10000;
int a;
scanf("%d",&a);
do{
int d = a / mask;
printf("%d",d);
a %= mask;
mask /= 10;
if(a > 0){
printf(" ");
}
}while(mask > 0);
printf("\n");
return 0;
}
13524 1 3 5 2 4
Process exited after 2.08 seconds with return value 0
在程序中适当位置添加printf模拟debug:
#include <stdio.h>
int main()
{
int mask = 10000;
int a;
scanf("%d",&a);
do{
int d = a / mask;
a %= mask;
mask /= 10;
printf("a=%d d=%d mask=%d",a,d,mask);
printf("\n");
}while(mask > 0);
return 0;
}
15243 a=5243 d=1 mask=1000 a=243 d=5 mask=100 a=43 d=2 mask=10 a=3 d=4 mask=1 a=0 d=3 mask=0
Process exited after 2.144 seconds with return value 0
使用边界值再次执行程序:
50000 50000
Process exited after 2.467 seconds with return value 0
输入50000后,发现程序没有正确执行,在第一次执行a%mask时,50000%10000->0,此时a=0,原因可能是条件出现了问题,改进如下:
#include <stdio.h>
int main()
{
int mask = 10000;
int a;
scanf("%d",&a);
do{
int d = a / mask;
printf("%d",d);
a %= mask;
mask /= 10;
if(mask > 0){
printf(" ");
}
}while(mask > 0);
printf("\n");
return 0;
}
50000 5 0 0 0 0
Process exited after 1.996 seconds with return value 0
上述程序的mask都是早已知数字位数后指定的,设计一个程序自动读取判断数字位数:
#include <stdio.h>
int main() { int mask =1; int a; scanf("%d",&a); do{ a /= 10; mask *= 10; } while(a > 0); printf("mask=%d",mask); return 0; }
15243 mask=100000
Process exited after 2.513 seconds with return value 0
mask多了一位,表明循环多进行了一轮,可以通过控制循环条件来控制循环次数:
#include <stdio.h>
int main() { int mask =1; int a; scanf("%d",&a); do{ a /= 10; mask *= 10; } while(a > 9); printf("mask=%d",mask); return 0; }
15243 mask=10000
Process exited after 1.781 seconds with return value 0
数字位数正确,使用边界值进一步验证:
5 mask=10
Process exited after 0.8986 seconds with return value 0
当数字位数为1时,mask值应为1。
分析原因:do-while循环不论输入数字位数都会先执行一轮循环语句mask*=10,使得输出mask值最小也是10,只需要将程序从do-while循环变为while循环就可以:
#include <stdio.h>
int main() { int mask =1; int a; scanf("%d",&a); while(a > 9){ a /= 10; mask *= 10; } printf("mask=%d",mask); return 0; }
15423 mask=10000
Process exited after 2.596 seconds with return value 0
5 mask=1
Process exited after 1.142 seconds with return value 0
把mask判断的程序加进原程序:
#include <stdio.h>
int main() { int mask =1; int a; scanf("%d",&a); while(a > 9){ a /= 10; mask *= 10; } printf("mask=%d\n",mask); do{ int d = a / mask; printf("%d",d); a %= mask; mask /= 10; if(mask > 0){ printf(" "); } }while(mask > 0); printf("\n"); return 0; }
15423 mask=10000 0 0 0 0 1
Process exited after 1.751 seconds with return value 0
发现原程序的运算结果不正确,原因是在判断mask的循环中,输出数字a已经被使用,无法再以输入大小进行后面的循环,需要引入一个新的变量保证输入数字a不受影响:
#include <stdio.h>
int main() { int mask =1; int a; int b; scanf("%d",&a); b = a; while(b > 9){ b /= 10; mask *= 10; } printf("mask=%d\n",mask); do{ int d = a / mask; printf("%d",d); a %= mask; mask /= 10; if(mask > 0){ printf(" "); } }while(mask > 0); printf("\n"); return 0; }
5 mask=1 5
Process exited after 3.5 seconds with return value 0
50000 mask=10000 5 0 0 0 0
Process exited after 1.901 seconds with return value 0
15423 mask=10000 1 5 4 2 3
Process exited after 2.847 seconds with return value 0
``` ::: warning 需要注意语句添加的位置,上述程序中b=a需要在scanf输入a的值后,否则会将a的初始值0赋给b,不会把a的输入值赋予b,后续循环中b的值会一直为0。 :::