C语言入门实例——水仙花数 |遍历|循环

关于仙花数

水仙花数,指一个N位正整数(N≥3),它的每个位上的数字的N次幂之和等于它本身。

例如三位数字(N=3): 153=13+53+33

这里我们使用C语言生成一定位数的水仙花数(由于int有上限)

实现思路

遍历所给位数能包含的所有整数,判断他们是不是水仙花数,如果是则输出。

如果我们想遍历一定位数内的所有数字我们首先要找到他位数范围内的最小值和最大值。

很显然地,对于3位数100,最小为100,最大则为999。而最大值可以用100✖10-1获得,也可以直接判断某个数<100✖10(因为是整数,所以<100✖10的最大值就是999)。因此任意位数范围N内的最小值就是10N,此处我们暂时不使用pow函数直接进行幂运算,因此我们可以有以下代码。

//上下代码略
    int  N, tN;
    scanf("%d", &N);
    tN = N;
    //此处为了保留N值以备后用
    //我们给定基础数字一个初始值1,每次让他乘以10,在tN<=1时截至。
    //例如我们给出数字3,他则会循环两次,最后得到结果100.
    for (base_number = 1; tN > 1; tN--) {
        base_number *= 10;
    }
//上下代码略

得到这个基础数字后,我们就可以对这个位数范围内的所有数字进行遍历

#include 
#include 

int main() {
    int  N, tN, number, base_number;
    scanf("%d", &N);
    tN = N;
    for (base_number = 1; tN > 1; tN--) {
        base_number *= 10;
    }
    for (number = base_number; number < base_number * 10; number++) {
        printf("%d\n", number);
    }
    system("pause");
    return 0;
}

那么我们如何判断这个数字是否是水仙花数呢?我们需要把这个数字拆分出来,例如1234,拆分为1,2,3,4。该如何进行呢?我们之前尝试过利用在int下取余和除法运算来拆解一个固定位数的数字,下面我们以1234为例由左往右依次拆解。

ps:以下只是其中一个思路,如果你看了下觉得麻烦,这里再提供第二种,对于任意数对10取余我们都能得到他最右边的一位数,例如1234%10=4,因此我们想要得到1234的每一位只需要1234%4,1234/10 =123%10 =3,123/10 =12 %10 =2 ,12/10=1 %10 = 1,这样就得到了每一位的结果,下面是另一种方法,显得有些笨重,但是可以看着玩玩

首先最左边是“1”,我们知道 1234 / 1000 = 1.234 而在int下小数点部分会略去,于是我们就得到了1234/1000 =1。

其次是“2”,我们知道1234 % 1000 = 234,也就是1234/1000会余234,而这里我们想得到“2”可以同上对234进行除法运算,即234/100 = 2。

其次是“3“,我们知道1234 % 100 = 34,34/10 =3。

最后是“4”,我们知道 1234 % 10 =4。

简单归纳一下上面的步骤,对于任意四位数m,我们通过以下四步对他进行拆解。

m/1000
m%1000/100
m%100/10
m%10

既然我们要写成代码,而且要扩展到任意位数,我们必须要找到他的一个通用的“公式”,因为我们要让每一次运算都是固定的算法,而不是有的有除法,有的有取余,有的二者都有,并且要让他们和某个参数形成关系。

我们知道1234%10000 = 1234,这样的话我们第一次运算就可以写作

m%10000/1000

对于最后一次运算m%10,我们可以把他看作m%10/1

这样的话我们就得到了

m%10000/1000
m%1000/100
m%100/10
m%10/1

这些位数是不断变少的,每次都是除以0。

而且对于这样一个四位数,我们进行了四次运算,从他的最小值的十倍和最小值开始进行除法和取余运算。因此我们可以把它写作一个for循环。

//上下代码略
  	//每次循环都会对m除以10,直到他等于1,这样就扩展到了任意位数(相对)
  	//由于每个数字都拆解很容易刷屏这里不建议printf
      for (m = base_number * 10; m >= 10; m /= 10) {
           int single_nubmer= number % m / (m / 10);
              //printf("%d",single_number);     
    }
//上下代码略

既然我们有了单独的位数,我们再对他进行N次方运算,把每一位数的结果相加与自身比较,就可以得出这个数字是不是水仙花数了,以下是完整代码。

// Narcissistic number
// BY MAXC 2020/07/06
#include 
#include 

int main() {
    int  N, tN, number, base_number,m;
    scanf("%d", &N);
    tN = N;
    for (base_number = 1; tN > 1; tN--) {
        base_number *= 10;
    }

    for (number = base_number; number < base_number * 10; number++) {
        // printf("%d\n", t);
        int sum = 0;
        for (m = base_number * 10; m >= 10; m /= 10) {
                int single_nubmer= number % m / (m / 10);
                //我们计算出了某一位数
                //这里引入一个新的变量用于后面的次方运算
                int pro_number = single_nubmer;
                //之前保存的N有用了。
                //循环到q<=1,我们就可以得到single_number的N次方
                for (int q = N; q > 1; q--) {
                    pro_number *= single_nubmer;
                }
                //每次N次方的循环结束我们把它都加到一个总和里
                sum += pro_number;
        }
        //最后拆解循环和次方循环都结束后我们让这个总和和自身比较
        // 相等就是水仙花数
        if (sum == number) {
            printf("%d\n", number);
        }
    }

    system("pause");
    return 0;
}

写到最后

以上代码不是唯一结果,似乎效率也不是很高,但是总体思路是我写的过程中比较流畅的,如果你有更好的思路欢迎在评论区提出,以上思路分析希望可以帮到你。

在这里并没有引入函数的感念,实际上当我们使用多个函数进行配合时整体代码会显得更有条理性。例如我们可以单独封装一个n次幂的函数(pow),以及判断一个数是不是水仙花数的函数然后在主函数中进行调用。

你可能感兴趣的:(笔记,C语言,c语言,入门教程)