帮初学者改代码——playerc之“练习:求完数问题”(下)
前文链接:帮初学者改代码——playerc之“练习:求完数问题”(上)
再来看看be_ferfect()应该如何改。
be_ferfect()函数的功能是判断number是否为完数,同时把因子对写入divisers数组。以28这个完数为例,在数组中将依次写入
1 28 2 14 4 7
输出时则按要求依大小次序输出 1 2 4 7 14。先从前跳到后,到头之后掉头,再从后跳到前。
这种写入的方式决定了输出代码写起来要困难一些。如果希望输出写得容易些的话,写入时就必须改变这种图省事的办法。
有很多种方案可选:
第一种方案,从小到大写
1 2 3 4 5 6 7 8 9 10 11 | int divisers_count = 1 ; for ( i = 2 ; i < number ; ++ i ){ if (!( number % i)){ divisers[divisers_count ++ ] = i; sum += i; if ( sum > number ) return false ; } } |
这显然简洁多了。作者没有考虑这种方法应该是有自己的想法,估计是认为一对儿一对儿的写更快些。对比一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | int divisers_count = 2 ; for ( i = 2 , i_max = sqrt (number)+1 ; i < i_max ; ++ i ){ if (!(number % i)){ divisers[divisers_count ++ ] = i; sum += i; diviser = number / i ; if ( diviser != i ) { divisers[ divisers_count ++ ] = diviser; sum += diviser; } if ( sum > number ) return false ; } } |
作者的写法做了大约2√n次除法、求余和不等于运算,而第一种方案要做n-1次除法。作者的写法虽然复杂,但优势还是有一些的。
第二种方案,用两个数组存储因子
1 2 4
28 14 7
这样即保留了作者算法的优势,输出的代码也比较容易写。但这要整个地修改代码的基本数据结构,改动比较大。所以这里就不用了。
第三种方案,从数组两头向中间存储
1 2 4 0 0 0 …… 7 14
这种方案,虽然看起来有点别扭,但读写数组都更容易些,也不需要改动数据结构,权衡之下,是唯一较为可取的方案。
采用这种方案的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | #include <stdio.h> #include <stdbool.h> bool be_ferfect( int , int * , int * ); void output( int [] , int ); #define TOP (10000) #define DIVISERS_MAX_LENGTH ((3+1)*(1+1)*(1+1)*(1+1)*(1+1)) int main( void ) { int number; for ( number = 2 ; number < ( TOP + 1 ) ; ++number ){ int divisers[DIVISERS_MAX_LENGTH] = { 1 } ; if ( be_ferfect( number , divisers , divisers + DIVISERS_MAX_LENGTH - 1 ) ){ printf ( "%d ,Its factors are : " , number) ; output ( divisers , DIVISERS_MAX_LENGTH ) ; } } return 0; } bool be_ferfect( int number , int * p_b , int * p_e ) { int i ; int sum = * p_b ++ ; for ( i = 2 ; i * i < number ; ++ i ){ if ( number % i != 0 ) continue ; sum += ( * p_b ++ = i ) + ( * p_e -- = number / i ) ; if ( sum > number ) return false ; } if ( i * i == number ) sum += ( * p_b ++ = i) ; return sum == number ; } void output ( int divisers[] , int size ) { int i ; for ( i = 0 ; i < size ; i ++ ){ if ( divisers[i] == 0 ) continue ; printf ( "%d " ,divisers[i]); } putchar ( '\n' ); } |
(完)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
2010-11-01 一个凶险的BUG