自幂数

Ⅰ 自幂数的定义

Ⅱ 需求分析

Ⅲ 算法优化

a. 得到当前数字的位数

b. 判断自幂数

Ⅳ 完整代码

Ⅰ 自幂数的定义

自幂数是指一个 n 位数,它的每个位上的数字的 n 次幂之和等于它本身。(例如:当n为3时,有1^3 + 5^3 + 3^3 = 153,153即是n为3时的一个自幂数)

自幂数包括:独身数、水仙花数、四叶玫瑰数、五角星数、六合数、北斗七星数、八仙数、九九重阳数、十全十美数

n为1时,自幂数称为独身数。显然,0,1,2,3,4,5,6,7,8,9都是自幂数。

n为2时,没有自幂数。

n为3时,自幂数称为水仙花数,有4个:153,370,371,407;

n为4时,自幂数称为四叶玫瑰数,共有3个:1634,8208,9474;

n为5时,自幂数称为五角星数,共有3个:54748,92727,93084;

n为6时,自幂数称为六合数, 只有1个:548834;

n为7时,自幂数称为北斗七星数, 共有4个:1741725,4210818,9800817,9926315;

n为8时,自幂数称为八仙数, 共有3个:24678050,24678051,88593477;

n为9时,自幂数称为九九重阳数,共有4个:146511208,472335975,534494836,912985153;

n为10时,自幂数称为十全十美数,只有1个:4679307774。

Ⅱ 需求分析

该程序的目的是输出一定范围内的所有自幂数,要判断一个数是不是自幂数,我们需要得到它的位数,然后根据每位的位数次方之和来判断该数是不是自幂数。

得到位数以及次方和,便是这个程序的主要步骤,因此,优化该程序也应从这两部的效率最高的方法考虑。

在我的哥德巴赫猜想验证的博客中,我给出了一个代码从最初级到极限的算法优化全部步骤,感兴趣的同学可以移步去看那篇文章,在此我不再赘述,直接考虑自幂数算法的极限情况。

【C语言】->哥德巴赫猜想验证->筛选法->算法极限优化之你不可能比我快

Ⅲ 算法优化

a. 得到当前数字的位数

关于这一步,惯常的想法是通过不断 /10 得到位数,事实上最快的做法是用 if 条件语句直接判断。由于int类型最大数是42亿左右,十全十美数已经超过了这个范围,所以我们只考虑十位以下的数。

int getBits(int number) {

if (number >= 100000000 && number < 1000000000) {

return 9;

}

if (number >= 10000000 && number < 100000000) {

return 8;

}

if (number >= 1000000 && number < 10000000) {

return 7;

}

if (number >= 100000 && number < 1000000) {

return 6;

}

if (number >= 10000 && number < 100000) {

return 5;

}

if (number >= 1000 && number < 10000) {

return 4;

}

if (number >= 100 && number < 1000) {

return 3;

}

if (number >= 10 && number < 100) {

return 2;

}

if (number >= 0 && number < 10) {

return 1;

}

}

这里还有个需要注意的地方,就是要从最大位数开始判断,因为往后数字越大最后判断自幂数的时间就越长,所以把最大的数放在靠上面的语句,这样可以更快的得到更大数的位数,即使只是省了几行语句的时间。

b. 判断自幂数

要知道一个数是不是自幂数,我们需要将每一位的数字的位数次方加起来,然后和本身做比较。这就牵扯到每次判断可能都要调用pow()函数,但是这样是很花时间的。

在做哥德巴赫猜想验证时,我们先生成了一个质数池,每次判断一个数是不是质数,直接在质数池中取就知道了。同样的思路,我们判断自幂数时,不用当场算它的幂级数,而是直接取。这就用到了二维数组。

因为每个数字的每一位上只可能是0 到 9 这十个数字,且数字的位数也是0 到 9位,所以其幂指数也是只可能是 0 到 9 这十个数字。所以我们先算完,然后存入二维数组中,到时候直接调取就好了。

const int array[10][10] = {

/*0*/1, 1, 1, 1, 1, 1, 1, 1, 1, 1,

/*1*/0, 1, 2, 3, 4, 5, 6, 7, 8, 9,

/*2*/0, 1, 4, 9, 16, 25, 36, 49, 64, 81,

/*3*/0, 1, 8, 27, 16*4, 125, 36*6, 49*7, 64*8, 81*9,

/*4*/0, 1, 16, 81, 16*4*4, 125*5, 36*6*6, 49*7*7, 64*8*8, 81*9*9,

/*5*/0, 1, 32, 243, 16*4*4*4, 125*5*5, 36*6*6*6, 49*7*7*7, 64*8*8*8, 81*9*9*9,

/*6*/0, 1, 64, 729, 16*4*4*4*4, 125*5*5*5, 36*6*6*6*6, 49*7*7*7*7, 64*8*8*8*8, 81*9*9*9*9,

/*7*/0, 1, 128, 729*3, 16*4*4*4*4*4, 125*5*5*5*5, 36*6*6*6*6*6, 49*7*7*7*7*7, 64*8*8*8*8*8, 81*9*9*9*9*9,

/*8*/0, 1, 256, 729*3*3, 16*4*4*4*4*4*4, 125*5*5*5*5*5, 36*6*6*6*6*6*6, 49*7*7*7*7*7*7, 64*8*8*8*8*8*8, 81*9*9*9*9*9*9,

/*9*/0, 1, 512, 729*3*3*3, 16*4*4*4*4*4*4*4, 125*5*5*5*5*5*5, 36*6*6*6*6*6*6*6, 49*7*7*7*7*7*7*7, 64*8*8*8*8*8*8*8, 81*9*9*9*9*9*9*9,

};

我用const定义了一个二维数组,所以不需要每一个值我都计算出来,这些数会在预编译的过程中由C语言编译器直接计算完成,不会占用程序运行的时间。

其行为幂指数,列为对应的位。

所以判断自幂数的代码如下

boolean isSelfPower(int number, int bits) {

int i;

int bit;

int sum = 0;

int num = number;

for (; sum <= number && num; num /= 10) {

bit = num % 10;

sum += power(bits, bit);

}

return sum == number;

}

int power(int bits, int number) {

return array[bits][number];

}

那么这两个关键步骤已经优化完成了。

Ⅳ 完整代码

#include

#include

const int array[10][10] = {

/*0*/1, 1, 1, 1, 1, 1, 1, 1, 1, 1,

/*1*/0, 1, 2, 3, 4, 5, 6, 7, 8, 9,

/*2*/0, 1, 4, 9, 16, 25, 36, 49, 64, 81,

/*3*/0, 1, 8, 27, 16*4, 125, 36*6, 49*7, 64*8, 81*9,

/*4*/0, 1, 16, 81, 16*4*4, 125*5, 36*6*6, 49*7*7, 64*8*8, 81*9*9,

/*5*/0, 1, 32, 243, 16*4*4*4, 125*5*5, 36*6*6*6, 49*7*7*7, 64*8*8*8, 81*9*9*9,

/*6*/0, 1, 64, 729, 16*4*4*4*4, 125*5*5*5, 36*6*6*6*6, 49*7*7*7*7, 64*8*8*8*8, 81*9*9*9*9,

/*7*/0, 1, 128, 729*3, 16*4*4*4*4*4, 125*5*5*5*5, 36*6*6*6*6*6, 49*7*7*7*7*7, 64*8*8*8*8*8, 81*9*9*9*9*9,

/*8*/0, 1, 256, 729*3*3, 16*4*4*4*4*4*4, 125*5*5*5*5*5, 36*6*6*6*6*6*6, 49*7*7*7*7*7*7, 64*8*8*8*8*8*8, 81*9*9*9*9*9*9,

/*9*/0, 1, 512, 729*3*3*3, 16*4*4*4*4*4*4*4, 125*5*5*5*5*5*5, 36*6*6*6*6*6*6*6, 49*7*7*7*7*7*7*7, 64*8*8*8*8*8*8*8, 81*9*9*9*9*9*9*9,

};

typedef unsigned char boolean;

int getBits(int number);

int power(int bits, int number);

boolean isSelfPower(int number, int bits);

boolean isSelfPower(int number, int bits) {

int i;

int bit;

int sum = 0;

int num = number;

for (; sum <= number && num; num /= 10) {

bit = num % 10;

sum += power(bits, bit);

}

return sum == number;

}

int power(int bits, int number) {

return array[bits][number];

}

int getBits(int number) {

if (number >= 100000000 && number < 1000000000) {

return 9;

}

if (number >= 10000000 && number < 100000000) {

return 8;

}

if (number >= 1000000 && number < 10000000) {

return 7;

}

if (number >= 100000 && number < 1000000) {

return 6;

}

if (number >= 10000 && number < 100000) {

return 5;

}

if (number >= 1000 && number < 10000) {

return 4;

}

if (number >= 100 && number < 1000) {

return 3;

}

if (number >= 10 && number < 100) {

return 2;

}

if (number >= 0 && number < 10) {

return 1;

}

}

int main() {

int i;

int bits;

int ceiling;

long startTime;

long endTime;

printf("请输入最大数:");

scanf("%d", &ceiling);

startTime = clock();

for (i = 1; i < ceiling; i++) {

bits = getBits(i);

if (isSelfPower(i, bits)) {

printf("%d\n", i);

}

}

endTime = clock();

endTime -= startTime;

printf("消耗时间:%d.%03ds\n", endTime / 1000, endTime % 1000);

return 0;

}

运行结果如下:

n为6时

只消耗了0.048秒。

n为8时

消耗时间6.022秒。

到了最大位,n为9时

消耗了一分多,前面其实都很快,找到最后一个数花费了很多时间。

所以快的像一道闪电是骗你们的,不过已经很快了,毕竟不是个简单的事。

下面这个才是快得像闪电一样,并且已经优化到了极致。感兴趣的同学可以移步此处。

【C语言】->哥德巴赫猜想验证->筛选法->算法极限优化之你不可能比我快

以上即为我对查找自幂数的算法优化,大家可以再多加尝试,找到更好的方法来优化。

c语言编程自幂数,【C语言基础】-自幂数优化-这个算法快得像一道闪电相关推荐

  1. Go语言编程笔记12:web基础

    Go语言编程笔记12:web基础 图源:wallpapercave.com 开一个新坑,用Go来做web开发.虽然已经从事多年基于LAMP的web开发,但最近学习了Go编程,所以打算借着学习<G ...

  2. 罗定c语言,罗定学c语言编程,罗定学c语言编程培训,罗定学c语言编程一般怎么收费...

    罗定学c语言编程,罗定学c语言编程培训,罗定学c语言编程一般怎么收费 首页 > 软件 > 罗定学c语言编程 作者:镀金池   发布时间:2018-10-04 23:40 依照c语言的法则, ...

  3. c语言编程技巧分析,C语言难点及编程技巧分析

    摘要:近些年信息技术发展迅速,社会需要大量专业的计算机人才,C语言是学习计算机知识的专业理论课程,能够为以后的学习打下专业基础.但目前C语言学习受到各方面因素的影响,学习效果不是很理想,很多时候即使努 ...

  4. c语言编程模拟选举,C语言编程题精选

    C语言编程题精选 C语言编程题精选 1. 编程实现对键盘输入的英文名句子进行加密.用加密方法为,当内容为英文字母时其在26字母中的其后三个字母代替该字母,若为其它字符时不变. 2. 编程实现将任意的十 ...

  5. 成都c语言编程培训机构,成都学c语言编程,成都学c语言编程去哪里,成都学c语言编程需要报培训班吗...

    成都学c语言编程,成都学c语言编程去哪里,成都学c语言编程需要报培训班吗 首页 > 软件 > 成都学c语言编程 作者:镀金池   发布时间:2018-09-28 14:20 近似带有序布局 ...

  6. 单片机c语言编程下载,单片机C语言编程.doc

    单片机C语言编程.doc 单片机C语言编程指令格式 功能简述 字节数 周期 一.数据传送类指令 MOV A, Rn 寄存器送累加器 1 1 MOV Rn,A 累加器送寄存器 1 1 MOV A ,Ri ...

  7. c语言编程宝典pdf,C语言编程宝典之一.pdf

    C语言编程宝典之一 作者:王大刚 本人的<FOXPRO编程宝典之一>,<FOXPRO编程宝典之二>和<FOXPRO 编程宝典之三>系列软件在<电脑报>配 ...

  8. 数学C语言编程,数学规划 (最速下降法,c语言编程).doc

    数学规划 (最速下降法,c语言编程).doc 数 学 规 划 课 程 设 计 题目:用最速下降法求解无约束非线性规划问题 姓名: 学号: 成绩: 2011年6月 用最速下降法求解无约束非线性规划问题 ...

  9. 分三种情况C语言编程,浅谈C语言教学的现状及几点建议.doc

    浅谈C语言教学的现状及几点建议 浅谈C语言教学的现状及几点建议 摘 要 针对C语言教学中存在的问题提出建议,以期对C语言教学有一定帮助. 关键词 C语言:课程设置:创新能力 中图分类号:G642 文献 ...

最新文章

  1. nginx自定义模块编写-实时统计模块--转载
  2. JS每日一题:Vue中的diff算法?
  3. week04_python函数返回值、作用域
  4. java调用c写的dll jna_jna调用c编写的dll
  5. 先序,中序,后序线索二叉树
  6. String类的特点和使用步骤
  7. java中原始数据文件的输入
  8. Makefile(1):基本使用
  9. mac系统虚拟机上的Linux系统的使用说明
  10. 计算机错误英语,计算机启动提示:引导时解释英语错误消息的含义
  11. word删除内容后不删除书签_Word涨薪88式第三式:书签的妙用
  12. Win7 XAMPP apache无法启动的问题
  13. ASP.NET 2.0中合并 GridView 的表头单元格
  14. property attribute: assign, strong, weak, unsafe_unretain and copy
  15. [机器学习实战] 基于概率论的分类方法:朴素贝叶斯
  16. oa办公系统文件存取错误_出现文件存取错误解决方法
  17. Excel里面自动获取当前时间
  18. Java读取hdfs文件权限问题
  19. oracle数据库纵向转横向,复杂SQL语句实现表中数据横向变纵向问题求解
  20. c语言感叹号放最后用法,感叹号的用法和注意事项

热门文章

  1. android 听筒模式外放模式的切换,YY项目之Android 听筒 扬声器 切换
  2. Excel如何批量修改工作表名称
  3. 安装kali步骤(超级超级详细)
  4. 使用html和css的一些案列(小米官网)
  5. 大学生笔记本选Mac还是Windows?
  6. hr员工数据分析(实战)
  7. Revit二次开发之 自定义选项卡排在最前端
  8. hualinux 编程概念 3.11 快速原型模型:以最快最小代价完成产品特性
  9. idea常用的一些配置信息
  10. UE5 学习2- 快捷键