当前位置: 首页 > article >正文

【C++】2029:【例4.15】水仙花数


在这里插入图片描述

博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳]
本文专栏: C++

文章目录

  • 💯前言
  • 💯题目描述
  • 💯我的做法
    • 思路分析
    • 优势
    • 不足之处
  • 💯老师的做法
    • 思路分析
    • 优势
    • 不足
  • 💯对比和优化
    • 实现方式对比
    • 优化思路和操作
      • 1. 直接分解数字的各位
      • 2. 展开至任意位数水仙花数
  • 💯小结


在这里插入图片描述


💯前言

  • 在程序设计中,“水仙花数”是一个带有数学特色的热点题目。这个题目最核心的思路在于如何分解三位数,并检查它是否满足水仙花数的定义。通过进一步分析、优化,我们不仅能学习到原理,还可以探索于实现与效率之间的平衡点。本文将从题目解读、我的实现、老师做法、思路对比与优化,以及指向临水仙花数更学机。
    C++ 参考手册
    在这里插入图片描述

💯题目描述

2029:【例4.15】水仙花数
在这里插入图片描述

题目要求如下:

  • 计算 100 到 999 中的水仙花数
    如果三位数 ( ABC ) 满足以下条件:
    A B C = A 3 + B 3 + C 3 ABC = A^3 + B^3 + C^3 ABC=A3+B3+C3
    则称 ( ABC ) 为水仙花数。

例如:三位数 153 ,其三位系数分别是:
1 3 + 5 3 + 3 3 = 1 + 125 + 27 = 153 1^3 + 5^3 + 3^3 = 1 + 125 + 27 = 153 13+53+33=1+125+27=153
则 153 是水仙花数。

输入:

  • 无需输入

输出:

  • 由小到大输出满足条件的数,每个数单独一行。

示例输出:

153
370
371
407

💯我的做法

我的做法如下:

#include <iostream>
using namespace std;

int main()
{
    for (int i = 100; i <= 999; i++) // 遍历所有三位数
    {
        int m = i; // 存储当前数字
        int count = 0; // 积累各位系数的立方和

        while (m)
        {
            int j = m % 10; // 取位:下一个位系数
            count += j * j * j; // 计算立方并积累
            m /= 10; // 清除最低位
        }

        if (count == i) // 检查积累立方和是否等于原数字
            cout << i << endl; // 输出
    }

    return 0;
}

在这里插入图片描述

思路分析

  1. 通过 for 循环遍历 [100, 999] 范围内的所有数字,以判断每个数字是否是水仙花数。
  2. 通过循环中的初始化:
    • 用临时变量 m 存储当前数字,无需直接操作原数。
    • 定义 count 用于积累各位系数立方和。
  3. 通过内部 while 循环:
    • 取位系数:通过 m % 10 获得最低位;
    • 计算立方值并积累:通过 j * j * j 直接计算立方值;
    • 清除最低位:通过 m /= 10,将数字左移一位;循环至数字为 0 为止。
  4. 检查立方积累和是否等于原数,如等,则输出。

优势

  • 简洁直观: 计算每个位系数立方直接通过三次乘法完成,避免使用更复杂的函数。
  • 处理简单: 通过循环直接完成数字分解、积累立方和,无需额外函数调用,更实用。

不足之处

  • 总处理时间复杂度为 ( O(n \times d) ),对于三位数,( d ) 是 3,因此复杂度为实际上是存在优化空间的,如果可直接计算各位,则可省去一些循环操作。
  • 输出格式比较基本,如需更好看的输出,可选择增加分隔符。

💯老师的做法

老师的代码如下:

#include <iostream>
#include <cmath> // 引入函数 pow

using namespace std;

int main()
{
    for (int i = 100; i <= 999; i++) // 遍历所有三位数
    {
        int tmp = i; // 临时处理数字
        int ret = 0; // 积累各位系数立方和

        while (tmp)
        {
            ret += pow(tmp % 10, 3); // 取位和立方,使用pow函数
            tmp /= 10; // 清除最低位
        }

        if (ret == i) // 检查积累立方和是否等于原数
            cout << i << endl; // 输出
    }

    return 0;
}

在这里插入图片描述

思路分析

  1. 核心比较:使用 pow 函数计算立方:
    老师的做法并没有用直接乘法计算立方,而是使用了标准库中的 pow 函数。这样做的好处是:在基础程序教学中,比较直观,学生能学习标准函数的应用;同时使用 pow 计算任意次方,优质显而易见。

  2. 居有化简:进一步生成临时变量,直接取位计算,治理系统优化:
    基于基础计算源,老师用 tmp 分解,保留原数,从维护和计算的规范性方面,有较高的规范性和应用性。

优势

  • 可读性更好: 使用 pow 函数,明确表达了“次方”的概念,更便于基础教学和理解。
  • 通用性更强: 如需更改次方,可直接修改为 pow(tmp % 10, n) ,适配与任意次方计算,更具通用性。

不足

  • 性能突出较少: 使用 pow 函数导致调用源库,效率上不如直接乘法。在计算量不大时,注意不显著;但如若展开到更大的数据量,远不如乘法计算的效率高。

💯对比和优化

实现方式对比

方式核心思想优势不足
我的做法通过三次乘法直接计算立方性能高,逻辑简洁,极对化相对基础学生,学习成本较高
老师做法使用 pow 函数计算立方可读性好,通用性强性能不如直接乘法,有调用源库的增加费用

优化思路和操作

在经典做法上,如下作举可能更加高效和实用:

1. 直接分解数字的各位

使用数学运算分解数字的各位,无需循环:

#include <iostream>
using namespace std;

int main()
{
    for (int i = 100; i <= 999; i++)
    {
        int a = i / 100;       // 百位
        int b = (i / 10) % 10; // 十位
        int c = i % 10;        // 个位

        if (i == a * a * a + b * b * b + c * c * c)
            cout << i << endl;
    }
    return 0;
}

在这里插入图片描述

在这里插入图片描述

这种做法可以直接获取各位,避免伴随调用和循环,效率更高。

2. 展开至任意位数水仙花数

通过使用函数展开计算任意位数的水仙花数:

#include <iostream>
#include <cmath>
using namespace std;

// 检查水仙花数
bool isArmstrong(int n)
{
    int sum = 0, tmp = n;
    int digits = log10(n) + 1; // 位数

    while (tmp)
    {
        sum += pow(tmp % 10, digits); // 次方积累
        tmp /= 10;
    }
    return sum == n;
}

int main()
{
    for (int i = 100; i <= 999; i++)
    {
        if (isArmstrong(i))
            cout << i << endl;
    }
    return 0;
}

在这里插入图片描述

在这里插入图片描述


💯小结

通过对我和老师做法的分析,我们能看到:

  1. 核心思想相同: 我和老师都是通过数字分解和立方积累,实现水仙花数的检查。
  2. 实现途径带有小差异: 我的做法更重视性能,老师做法更重视可读性。
  3. 优化思考: 通过直接分解数字和展开至任意位数,可以更加高效和通用。

在实际经验中,可根据场景和需求选择最适合的方案,例如教学中选择通过性更强的方案,而在效率优先的场景下,可选择性能更高的直接乘法。求真时,始终是计算积累的深层探索!


在这里插入图片描述


在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述


http://www.kler.cn/a/460740.html

相关文章:

  • AE RFG 1251 Generator User Manual
  • Vue2: table加载树形数据的踩坑记录
  • STM32 + 移远EC800 4G通信模块数传
  • SpringCloudAlibaba实战入门之Sentinel服务降级和服务熔断(十五)
  • 【three.js】材质(Material)
  • C# 设计模式(结构型模式):代理模式
  • Python列表推导常见问题解析:高效编程的陷阱与避坑指南
  • DeepSeek V3“报错家门”:我是ChatGPT
  • 【brew安装失败】DNS 查询 raw.githubusercontent.com 返回的是 0.0.0.0
  • 电子电气架构 --- 汽车电子电器设计概述
  • 用Pyside6 和sqlite3 重写了《电脑装配单》 加入切换主题 样式
  • 构建一个rust生产应用读书笔记7-确认邮件3
  • 【信息系统项目管理师】高分论文:论信息系统项目的沟通管理(不动产登记系统)
  • Python世界:人生苦短,我用Python
  • 一文讲清楚CSS3新特性
  • Hessian 矩阵与函数的凸性
  • 网络渗透测试实验二:网络嗅探与身份认证
  • 从零到一:构建高效、安全的电商数据API接口
  • Leetcode 从中序与后序遍历序列构造二叉树
  • Rocky Linux 下安装Liboffice
  • 计算机网络 (17)点对点协议PPP
  • Android音频效果处理:基于`android.media.audiofx`包的原理、架构与实现
  • WPF中的Microsoft XAML Behaviors包功能详解
  • 基于 Spring AI 孵化一款 AI 产品
  • 踩坑之服务器时间和本地时间相差8小时
  • C#语言的软件工程