这是最近不少少年儿童学习者都在讨论LOGO语言“自幂数”的编程问题。所谓“自幂数”其实很容易理解:如果说“3阶”的自幂数,其实就是“3位”的自幂数。153就是一个3阶的自幂数,因为153符合以下性质,它的3个数位的3次乘方(或称为3次幂)的和,正好等于它自身153。就是1×1×1+5×5×5+3×3×3=153。推广开来:N阶的自幂数的各个数位的N次乘方的和也就正好等于这个N位的自幂数本身。查找“自幂数”很明显涉及到极其巨量的数学计算、难度可想而知:就以3阶自幂数来说,所有的3位数从100~999共有900个3位数,每个数位都要计算3次乘方,然后求和,这要有多大的耐心?!从80年前人类还没有开始使用计算机的时代,许多先驱者们早已乐此不疲地进行计算。到现在人们知道总共才有88个自幂数,最大的自幂数竟然有39位。想想看:39位数有多少个?每个数位都要计算39次乘方、最后再求和。计算量及难度可想而知。但凡是自从有了电子计算机之后,计算、寻找自幂数就容易多了(但是这仍然涉及到普通计算机可能需要计算上千年的庞大计算量——这在后面会讲到)。用计算机编程求解自幂数,是学习C、C++、PASCAL、LOGO、PYTHON等编程语言几乎绕不过去的一个基础命题,甚至还多次成为竞赛考试的试题。深入研究自幂数的LOGO编程,可以学习使用到计算机编程中多种最基础常用的编程技巧,所以是非常有价值的学习编程技巧的抓手。下面是最常见的LOGO语言编程求解3阶自幂数的例程源程序(还可能有更多种方式编程)。编程原理已经附注得很清楚了。
一.用三重循环产生所有3位数
to zms_a
for[b 1 9][
;循环产生百位数
for[s 0 9][
;循环产生十位数
for[g 0 9][
;循环产生个位数
make "h
:b*:b*:b+:s*:s*:s+:g*:g*:g ;求各位数的乘方和
make "sw
:b*100+:s*10+:g
;计算3位数的值
if
:h=:sw[pr :sw]]]] ;如果相等,就是找到了自幂数
end
各种不同的编程方式都输出了相同的答案,3阶自幂数有4个:153、370、371、407。
二.用单重循环产生100-999所有的3位数,然后用int等计算分解出各个数位。
to zms_b
for[i 100 999][
;产生100-999所有3位数
make "b int(:i/100) ;从中分解出百位数
make "hm :i-:b*100
;减去百位剩下后面视为及个位数
make "s int(:hm/10) ;分解出十位数
make "g :i-:b*100-:s*10
;减去百位及十位的值剩下的就是个位数
if
:b*:b*:b+:s*:s*:s+:g*:g*:g=:i[
;这是发现3位自幂数的条件
pr :i]]
end
三.用单重循环产生100-999所有的3位数,然后用remainder等计算分解出各个数位。Power
:b 3是计算:b的3次幂的命令。
to zms_c
for[i 100 999][ ;用循环产生出所有3位数
make "g remainder :i 10
;用求余算出个位数
make "s remainder (int(:i/10)) 10
;计算出十位数
make "b int :i/100
;计算出百位数
if(power :b 3)+(power :s 3)+(power :g 3)=:i[pr
:i]] ;符合3位自幂数条件
end
四.用单重循环产生100-999所有的3位数,然后用item命令直接读出各个数位。
to zms_d
for[i 100 999][
;产生出所有3位数
make "b item 1 :i
;用字表处理命令item剪取出第1位百位数
make "s item 2 :i ;剪取第2位十位数
make "g item 3 :i ;剪取第3位个位数
if
:b*:b*:b+:s*:s*:s+:g*:g*:g=:i[
;输出符合条件的3位自幂数
pr :i]]
end
五.用尾递归循环产生100-999所有3位数。注意输入启动命令时:i的起始参数值是100。
to zms_e
:i
if
:i>999[stop]
;当:i超过3位数时停止运算
make "b item 1 :i ;用字表处理命令item剪取出第1位百位数
make "s item 2 :i ;剪取第2位十位数
make "g item 3 :i ;剪取第3位个位数
if
:b*:b*:b+:s*:s*:s+:g*:g*:g=:i[
;输出符合条件的3位自幂数
pr :i]
zms_e :i+1 ;:i增长1后尾递归继续寻找符合条件的自幂数
end
六.这是一个并不太复杂的LOGO程序,小学四年级以上的LOGO编程学习者都有可能看懂这个程序。这个程序是能够“自动化”地求解1~8位自幂数的。从计算3位的自幂数开始,每增加1个数位计算的时间就要至少增加10倍!计算到8位的自幂数就要使用6494.26秒钟——大概一个多小时。对于PCLogo语言来说有效数位只有6位,理论上只能计算出6位的自幂数,更大的自幂数在PCLogo输出中已经使用“科学计数法”表示了。从道理上来看,MSWLogo-FMSLogo编程系统可以达到15个有效数位。但是希望在普通计算机上求解15位的自幂数是不现实的:估算起来至少需要计算到8位的10000000倍,就是6000×10000000÷86400÷365≈1902年。这显然是不可能的事。至于求解39位的自幂数,那一定是要使用“超级计算机”了。
to zms_f
make "g 0
;自幂数的个数清零
make "nn 1
;数字的位数从1位开始寻找
make "t0 timemilli ;记录这一轮开始计算的时间
make "t00 :t0
;记录全部计算开始的时间
type :nn pr "位自幂数:
for[i 1 99999999][ ;产生1~8位数所有的数字
make "h 0
;在对每个数字进行计算时将累加和清零
make "n count :i ;计算这个数字的位数
if :n>:nn[
;如果:n>:nn说明开始多了一位数
type "以上共有 type :g pr
"个数字 ;输出这一论共找到了几个自幂数
make "t1
timemilli
;计算当下即时时间
type "这一部分计算了 type
(:t1-:t0)/1000 pr "秒钟 pr[] ;输出前一轮计算的累计秒数
make "nn :n
;:nn是下一组自幂数的位数
type :nn pr
"位自幂数:
;输出下一轮自幂数的眉头
make "t0
timemilli
make "g 0
make "h 0]
for[j 1 :n][
;对当前数字的:n个数位逐个累加自幂数的和
make "h :h+power (item :j :i)
:n]
if :h=:i[
;如果符合自幂数的条件就输出这个自幂数
pr :i
make "g :g+1]]
;当下自幂数的个数累加1
type "以上共有 type :g pr "个数字
;在这一匹自幂数的末尾输出有关信息
make "t1 timemilli
type "这一部分计算了 type(:t1-:t0)/1000 pr "秒钟
pr[]
make "t1 timemilli
;记录全部计算终了的时间点
type "整个计算用了 type (:t1-:t00)/1000 pr "秒钟
;输出整个计算的时间
end
输出结果如下
1位自幂数:
1
2
3
4
5
6
7
8
9
以上共有9个数字
这一部分计算了0.063秒钟
2位自幂数:
以上共有0个数字
这一部分计算了0.016秒钟
3位自幂数:
153
370
371
407
以上共有4个数字
这一部分计算了0.046秒钟
4位自幂数:
1634
8208
9474
以上共有3个数字
这一部分计算了0.406秒钟
5位自幂数:
54748
92727
93084
以上共有3个数字
这一部分计算了4.243秒钟
6位自幂数:
548834
以上共有1个数字
这一部分计算了47.658秒钟
7位自幂数:
1741725
4210818
9800817
9926315
以上共有4个数字
这一部分计算了535.926秒钟
8位自幂数:
24678050
24678051
88593477
以上共有3个数字
这一部分计算了5905.777秒钟
整个计算用了6494.26秒钟
6000×10000000÷86400÷365≈1902年
计算到8位自幂数已经足够了
我们已经涉猎到多种LOGO编程的基础算法