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

一、自幂数

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,还包括 370371407
  • 四位数的自幂数 :例如 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内的自幂数:

cpp 复制代码
#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的每个整数检查是否为自幂数,并打印出这个范围内所有的自幂数。

二、打印菱形

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

cpp 复制代码
#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、循环

cpp 复制代码
#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、递归

cpp 复制代码
#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,标志着程序的正常结束。

运行结果:

相关推荐
monkey_meng4 分钟前
【Rust中的项目管理】
开发语言·rust·源代码管理
喜欢打篮球的普通人6 分钟前
rust高级特征
开发语言·后端·rust
weixin_4786897610 分钟前
【回溯法】——组合总数
数据结构·python·算法
ModelBulider24 分钟前
十三、注解配置SpringMVC
java·开发语言·数据库·sql·mysql
戊子仲秋28 分钟前
【LeetCode】每日一题 2024_11_14 统计好节点的数目(图/树的 DFS)
算法·leetcode·深度优先
V搜xhliang024633 分钟前
基于深度学习的地物类型的提取
开发语言·人工智能·python·深度学习·神经网络·学习·conda
DK七七34 分钟前
多端校园圈子论坛小程序,多个学校同时代理,校园小程序分展示后台管理源码
开发语言·前端·微信小程序·小程序·php
苹果酱056738 分钟前
C语言 char 字符串 - C语言零基础入门教程
java·开发语言·spring boot·mysql·中间件
代码小鑫1 小时前
A032-基于Spring Boot的健康医院门诊在线挂号系统
java·开发语言·spring boot·后端·spring·毕业设计
训山1 小时前
4000字浅谈Java网络编程
java·开发语言·网络