C语言——小细节和小知识11

发布时间:2024年01月17日

一、自幂数

1、介绍

自幂数,也被称为阿姆斯特朗数,是一种特殊类型的数,在数学上具有一个有趣的性质:一个 n 位的正整数,其各个位上的数字的 n 次幂之和等于它本身。

这里是自幂数的定义步骤:

  1. 确定位数 (n): 首先,要确定一个数是几位数。例如,153 是一个三位数,因此 n = 3

  2. 计算每个位上的数字的 n 次幂:接着,将该数的每个位上的数字取出来,分别计算其 n 次幂。对于 153,计算如下:

    • 1?的三次幂是?1
    • 5?的三次幂是?125
    • 3?的三次幂是?27
  3. 计算这些幂的和:将上一步中得到的所有幂相加。对于 153,其和是 1 + 125 + 27 = 153

  4. 验证和是否等于原数:如果这个总和等于原来的数,则称该数为自幂数。所以,153 是一个自幂数,因为 1^3 + 5^3 + 3^3 = 153

不同位数的自幂数有不同的名称:

  • 三位数的自幂数:这些是最常见的自幂数,通常被称为水仙花数。除了前面提到的?153,还包括?370371?和?407
  • 四位数的自幂数:例如?1634,因为?1^4 + 6^4 + 3^4 + 4^4 = 1634
  • 五位数的自幂数:例如?54748,因为?5^5 + 4^5 + 7^5 + 4^5 + 8^5 = 54748
  • 依此类推,你可以找到更多位数的自幂数。

自幂数不仅局限于三位数,但随着位数的增加,自幂数也变得越来越稀少。自幂数是数学中的一个奇特现象,通常用于编程练习和算术游戏中。在数学理论中,除了被当作一种趣题外,并没有特别的意义。

我们常说的水仙花数就是三位的自幂数。

2、例子

打印0~100000内的自幂数:

#include <stdio.h>
#include <math.h>

int CountDigit(int x)//判断数字的位数
{
	int counter = 0;
	while (x)
	{
		x /= 10;
		counter++;
	}
	return counter;
}

int main()
{
	int i = 0,j = 0,s = 0,num = 0;
	for (i = 0; i <= 100000; i++)
	{
		num = i;
		int digits = CountDigit(i);
		for(s = 0,j = 0;j < digits;j++)
		{
			s += (int)pow(num % 10, digits);
			num /= 10;
		}
		if (s == i)
		{
			printf("%d ", i);
		}
	}
	return 0;
}

运行结果:

代码分析:

  1. CountDigit 函数:这个函数的目的是确定一个给定的整数 x 有多少位。它通过一个 while 循环实现:只要 x 不为0,就将 x 除以10,并将计数器 counter 加1。循环结束时,counter 就是 x 的位数。

  2. main 函数

    • 初始化了四个整型变量?i,?j,?s,?numi?将作为循环变量,j?将在内部循环中使用,s?用于累加幂的和,num?存储?i?的临时副本,防止?i?的值在内部循环中被改变。
    • 外层?for?循环:for (i = 0; i <= 100000; i++),它将从0迭代到100000,检查每个数是否是自幂数。
    • 在每次外层循环的迭代开始时,先将?i?的值赋给?num,然后调用?CountDigit(i)?函数得到当前?i?的位数,这个值存储在?digits?变量中,以便在后续计算中使用。
    • 内层?for?循环:for (s = 0, j = 0; j < digits; j++),用于计算?i?的每一位上的数字的?digits?次幂之和。每次循环:
      • num % 10?提取?num?的最后一位数字。
      • pow(num % 10, digits)?计算这个数字的?digits?次幂。
      • s += ...?将这个幂加到?s?上,s?是一个累加器,用来计算所有幂的和。
      • num /= 10?通过整数除法去除?num?的最后一位数字。
    • 当内层循环结束时,如果?s(幂的和)等于原始的数?i,则表明找到了一个自幂数,printf?函数将其打印出来。

整个程序的执行流程就是对从0到100000的每个整数检查是否为自幂数,并打印出这个范围内所有的自幂数。

二、打印菱形

编写一个程序用来打印菱形:

#include <stdio.h>

int main()
{
	int i = 0, j = 0,n = 0;
	scanf("%d", &n);//n应当为奇数
	for (i = 0; i < (n / 2) + 1; i++)
	{
		for (j = 0; j < (n / 2) - i; j++)
		{
			printf(" ");
		}
		for (j = 0; j < 2 * (i + 1) - 1; j++)
		{
			printf("*");
		}
		printf("\n");
	}
	for (i = 0; i < n / 2; i++)
	{
		for (j = 0; j < i + 1; j++)
		{
			printf(" ");
		}
		for (j = 0; j < n - 2 * (i + 1); j++)
		{
			printf("*");
		}
		printf("\n");
	}
	return 0;
}

程序的工作流程如下所述:

  1. 用户输入:程序首先提示用户输入一个整数 n,该值应该是奇数。

  2. 打印菱形的上半部

    • 外层?for?循环从?i = 0?迭代到?i < (n / 2) + 1。该循环负责打印菱形的上半部,包括最中间的一行。
    • 内层第一个?for?循环打印前置空格。对于菱形的每一行,前置空格的数量是?(n / 2) - i,这样星号后面的空格会随着每一行递增的?i?而递减。
    • 内层第二个?for?循环打印星号。每行的星号数量是?2 * (i + 1) - 1,这保证了星号的数量随着每一行递增的?i?而递增,每次增加两个星号(除了第一行)。
    • 每一行打印完星号和前置空格后,printf("\n")?打印一个换行符,以开始新的一行。
  3. 打印菱形的下半部

    • 外层?for?循环从?i = 0?迭代到?i < n / 2。该循环负责打印除了最中间的行以外的菱形下半部分。
    • 内层第一个?for?循环打印前置空格。对于下半部分的每一行,前置空格的数量是?i + 1,这样随着下半部分每一行递增的?i,前置空格也在递增。
    • 内层第二个?for?循环打印星号。每行的星号数量是?n - 2 * (i + 1),这确保了星号的数量随着下半部分每一行递增的?i?而递减,每次减少两个星号。
    • 与上半部一样,每一行打印完星号和前置空格后,printf("\n")?打印一个换行符,以开始新的一行。

最终,当所有循环执行完成时,如果 n 是一个奇数,你将得到一个完整的菱形图案。

这里是一个例子的输出,如果用户输入的 n5

三、买汽水

买汽水,一元一瓶,两个空瓶可以换一瓶汽水,20元可以喝几瓶。

1、循环

#include <stdio.h>

int main()
{
	int money = 0;
	scanf("%d", &money);
	int totalBottles = money;
	int emptyBottles = totalBottles;
	while (emptyBottles >= 2)
	{
		int newBottles = emptyBottles / 2;
		totalBottles += newBottles;
		emptyBottles = emptyBottles % 2 + newBottles;
	}
	printf("%d\n", totalBottles);
	return 0;
}

程序分析:

  1. 用20元钱买20瓶汽水,所以初始的空瓶数量也是20。
  2. 当你有2个或更多的空瓶时,继续执行循环:
    • 将空瓶数除以2得到新的汽水瓶数(因为2个空瓶可以换1瓶汽水)。
    • 把新的汽水瓶数加到总瓶数上。
    • 更新空瓶的数量,等于之前空瓶数除以2的余数加上新换得的汽水数量。
  3. 当你没有足够的空瓶换取汽水时,循环结束,此时 totalBottles?变量中存储的就是你能喝的汽水总数。
  4. 打印结果。

运行结果:

2、递归

#include <stdio.h>

int Func(int totalBottles, int emptyBottles)
{
	if (emptyBottles < 2)
	{
		return totalBottles;
	}
	int newBottles = emptyBottles / 2;
	return Func(totalBottles + newBottles, emptyBottles % 2 + newBottles);
}

int main()
{
	int money = 0;
	scanf("%d", &money);
	printf("%d\n", Func(money, money));
	return 0;
}

程序执行的流程大致如下:

  1. 程序启动后,进入main函数,这是每个C程序的入口点。

  2. 程序声明了一个整型变量money,用来存放用户通过标准输入提供的金额。

  3. 程序调用scanf函数等待用户输入一个整数,该整数代表用户用来购买汽水的金额。输入的整数将被保存在money变量中。

  4. 输入完毕后,程序调用Func函数,将money作为参数传入,这里有两个作用:一是表示初始时用这些钱可以直接买到的汽水数量,二是同样数量的空瓶可以开始进行换购。

  5. Func函数内部,首先检查当前的空瓶数量是否足够兑换更多的汽水。如果不足2个,则无法继续兑换,函数返回当前统计到的汽水总瓶数。

  6. 如果当前空瓶数量足够换更多汽水(即2个或2个以上),则计算能够兑换的新汽水瓶数,并更新空瓶数量(包括兑换后剩余的空瓶和新的空瓶)。

  7. Func利用递归调用自身,将更新后的汽水总数和空瓶数量作为新的参数,继续上述兑换过程。

  8. emptyBottles不再足以兑换新的汽水时,递归结束,Func函数返回最终计算的汽水总瓶数。

  9. main函数接收到Func函数返回的总瓶数后,通过printf函数输出到控制台。

  10. 最后,main函数执行完毕,返回0,标志着程序的正常结束。

运行结果:

文章来源:https://blog.csdn.net/stewie6/article/details/135629464
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。