数字黑洞(上):三位数的黑洞
黑洞是一个物理学概念,指的是一个巨大的引力场,连光都难以逃脱,因此,人类无法通过光的反射来证实它的存在。
数字黑洞借用了这个概念,指的是一个数字,经过多次变化和计算之后,总能得出某个固定的值。举例来说,一个三位数,如217,将其中的三个数字重新排列,可以得到一个最大值721和一个最小值127,用最大值减去最小值,即721-127,得到另一个三位数594;对594作同样的变化和计算,得出三位数495;对495再作同样的变化和运算,得到的三位数依旧是495,这个不再改变的495就被称作三位数的黑洞数。并不是所有的三位数都能计算出黑洞数,比如三个数字相同的三位数就被排除在外。
本文试图用程序的方法,展示求解三位黑洞数的过程,展示结果如图 1所示。
图1 三位黑洞数的求解结果
一、用户界面
在App Inventor开发环境中创建一个项目——数字黑洞1,向项目中添加组件,如图 2所示,组件的命名及属性设置见表 1。
图2 数字黑洞项目的用户界面设计
表1 组件的命名及属性设置
二、技术要点分析
对于一个给定的三位数,解题的第一步就是对其中的三个数字进行重新排序——求出由这三个数字组成的最大值和最小值。数字排序问题是编程技术中非常典型的问题,这个在人类看来不值一提的问题,计算机处理起来却显得笨拙,而且必须一丝不苟、步步为营。图 3中以135为例,给出了求最大值的排序方法。
图3 针对135的数字排序过程——求最大值
在上述排序方法中,涉及到两类操作——比较与交换位置,每项操作分别执行3次。如小图I中的1、3,首先通过比较确定1<3,然后让1、3交换位置。交换位置操作必须借助于一个临时容器,先将1存放在临时容器中,然后将3取出放在原来1的位置,最后再将临时容器中的1取出放在原来3的位置,这样才能完成两个数的位置交换。在程序语言中,比较操作与条件语句对应,而存放1、3、5的容器以及临时容器与变量对应。下面我们用程序来实现第一个目标:求三位数的极值——最大值及最小值。
三、编写程序——求三位数的极值
1、求最大值
按照图 3中给出的流程,创建一个有返回值的过程——最大值,过程的参数为“三位数”,代码如图 4所示。
过程中使用了“从文本中截取子串”块,将三位数分解为三个独立的数字,然后两两比较三个数字,如果前数<后数,则交换位置,最后再将三个排序之后的数字重新拼接成三位数。
图4 定义有返回值的过程——最大值
2、求最小值
与求最大值的方法相同,差别在于比较前后两个数时,小于号变为大于号,代码如图 5所示。
图5 定义有返回值的过程——最小值
四、编写程序——展示求解过程
我们的目标是将求解过程中的每个步骤显示在屏幕(标签)上,每次求差运算(最大值-最小值=新三位数)占一行。首先创建一个有返回值的过程——求差算式字串,以最大值和最小值为参数,代码如图 6所示。
图6 定义有返回值过程——求差算式字串
每次求差运算所得的新三位数,需要与上一次求差运算的结果进行比较,如果两个数相等,那么这个数就是黑洞数,为此我们需要声明一个全局变量——黑洞数,来记录每次求差运算的结果,如图 7所示,黑洞数的初始值为0。
图7 声明全局变量——黑洞数
利用上述过程及全局变量,我们来实现求解过程的记录及展示,定义一个过程——求差运算,过程包含两个参数——三位数及计算过程字串,代码如图 8所示。
图8 定义过程——求差运算
求差运算过程里使用了递归调用——在过程内部调用过程本身。首先,对于一个给定的三位数,求它的最大值、最小值及差值,并拼接计算过程字串;然后比较差值与黑洞数,如果差值不等于黑洞数,则让黑洞数等于差值,并调用“求差运算”过程本身,直到差值与黑洞数相等,再将计算过程字串显示在标签中。
求差运算过程设计的难点在于参数的设置,其中“三位数”可以将每次运算所得的差值传递给下一次调用,而“计算过程字串”可以将每次拼接字串的结果传递下去,这样确保求解过程的连续性。
最后,在求解按钮的点击事件中调用上述过程,代码如图 9所示。
图9 在求解按钮的点击事件中实现计算过程的展示
上述代码的测试结果如图 1所示,读者可以在完成代码的编写后,输入不同的三位数,查看求解过程。
注:本文已正式发表于《爱上机器人》杂志总第3期(2018.11)。