string去掉后四位_数字黑洞(下):四位数的黑洞

在上一期中我们展示了三位黑洞数的求解过程,其中的关键技术是数字的排序及位置交换。本期文章继续讨论有关数字黑洞的问题,展示四位黑洞数的求解过程。

一、用户界面

在App Inventor开发环境中打开上一期创建的项目——数字黑洞1,在项目菜单中选择“另存项目”,将项目名称修改为“数字黑洞2”,如图 1所示,保留项目中的全部组件。

6c60803d2c6c4d97db64d872a45b5cb6.png

图1 将“数字黑洞1”项目另存为“数字黑洞2”

二、技术要点分析

在求解三位黑洞数时,我们用局部变量(数1、数2、数3)保存三位数的三个数字,两两比较数的大小,根据比较结果决定是否将两个数交换位置,这样的处理过程需要3次比较,要编写3组共9条指令,如图 2所示,每组指令的格式相同。如果我们沿着同样的思路,对四个数字进行排序,那么就需要进行6次比较,编写6组共18条指令,同样每组指令的格式相同。

10352ba6879567f41b5dbda63aa7fd45.png

图2 三个条件语句中的代码格式相同

作为一个开发者,我们不能允许程序中出现如此多的重复代码,这些重复代码不仅让程序变得臃肿,而且当这部分代码需要修改时,极易给程序带来错误,例如由于疏忽忘记了修改其中的部分代码。

解决这一问题的关键技术有两点——列表与循环。将四位数的四个数字转换为列表,利用循环语句,对列表项进行两两比较,通过交换列表项的位置,来实现数字的排序。这也是解决大量数字排序问题的通用方法,例如,对班级考试成绩进行排序。

三、编写程序

将开发工具切换到编程视图,保留项目中的部分代码,将最大值、最小值过程删除,如图 3所示。

fc9326d4e334c7b286a90e4509dc0ca5.png

图3 保留项目中的部分代码

1、定义过程——数字转列表、列表转数字

为了利用列表和循环语句简化排序代码,首先需要将数字转化为列表,待排序完成后,再将列表转为数字,这样才能进行减法运算。代码如图 4及图 5所示。

4884f7f824908b0e529708ef7e3857cc.png

图4 定义过程——数字转列表

4791894f9e1fbd6d4934775d99a5b39d.png

图5 定义过程——列表转数字

2、定义过程——极值

在数学语言中,最大值、最小值统称为“极值”,这里定义一个有返回值的过程——极值,来取代最大值、最小值两个过程,代码如图 6所示。

1e4ec5e340ee967d3c2b8f9ab816bf68.png

图6 定义过程——极值

极值过程里使用了双层循环,外层循环变量“外层序号”的取值为1~3,内层循环变量“内层序号”的起始值为(外层序号+1),终止值为4,所有指令都包含在内层循环中。首先取出数字列表中的第1项,与后面3项进行两两比较,并交换位置,当第1次内层循环(共执行3次)结束时,列表中的第1项为四个数字中的最大数或最小数。接下来取出列表中的第2项,与后面两项进行比较并交换位置,当第2次内层循环(共执行2次)结束时,列表中的第2项为后三位数中的最大值或最小值,以此类推,当两层循环全部结束时,数字列表的排序完成。

注意:在交换两个列表项的位置时,同样需要一个临时变量,先将前数保存在临时变量中,然后用后数替换前数所对应的列表项,最后再用临时变量替换后数所对应的列表项。

极值过程里还使用了有返回值的条件语句,如果参数“极大”=真,则交换位置的条件为“前数后数”,并返回极小值列表。

3、改造过程——求差运算

首先将求差运算的“三位数”参数修改为“数字列表”,通过调用极值过程,求得四位数的最大值和最小值,再求两者的差值并拼接输出字串,比较差值与黑洞数(全局变量),如果差值不等于黑洞数,则继续调用求差运算过程(递归调用),直到差值与黑洞数相等,然后将输出字串显示在标签中。代码如图 7所示。

3cf05fbfa7a372c78990ffac0727e057.png

图7 改造之后的求差运算过程

4、改造求解按钮的事件处理程序

在求差运算过程中,第一个参数的数据类型由数字改成了列表,因此,在求解按钮的点击事件中,在调用求差运算过程时,要为过程提供列表类型的参数,此处利用数字转列表过程,将数字变为数字列表,代码如图 8所示。

72081ddd8785af18ec56a18a32fe80cf.png

图8 改造之后的点击事件处理程序

对上述代码进行测试,测试结果如图 9所示。

6e542ac44584585a36d9f561d1469213.png

图9 测试:四位黑洞数的求解过程

四、讨论

读者可能有疑问:图 7的求差运算过程里,在求最大值时,用“复制列表+数字列表”块作为极值过程的参数,而在求最小值时,则直接用“数字列表”作为参数,为什么会有这样的差别呢?我们先来做一个实验,将求差运算过程修改一下,代码及测试结果如图 10所示,最大值与最小值都成了最小值,这是什么原因呢?

5a8ff39007dd47b0e1731f07b610f7c8.png

图10 去掉“复制列表”块时的测试结果

原因在于列表类型数据的存储方式。简单类型的变量,如黑洞数,其中保存的是具体的数,如6193,而列表类型的变量,如参数“数字列表”(参数等同于变量),其中保存的不是具体的数据,而是数据存放的地址。举例来说,假设列表A、列表B为变量名,经过下列操作:

  1. 1.       设列表A = (6 1 9 3)

  2. 2.       设列表B = 列表A

  3. 3.       设列表B = (9 6 3 1)

此时查看列表A的值,会发现列表A也变成了(9 6 3 1)。

也就是说,第2步操作并没有真正生成一个变量,只是为“列表A”贴了一个“列表B”的标签,它们指向的是同一个数据存储区域,因此,对列表B的改写,同时也发生在列表A之上。

回到求差运算过程里,求差运算的参数“数字列表”、过程里的局部变量最大值、最小值,这三者指向的是同一个存储区域,而“复制列表”块所起的作用,是另外开辟一个存储区域,将“数字列表”的值复制到新区域中,因此求得的最大值保存在新区域中,而最小值其实是保存在参数“数字列表”所在的区域中。这就是使用“复制列表”块的缘由。

注:本文已正式发表于《爱上机器人》杂志总第4期(2019.01)。

357a09f091dd154955e79f3034fbfa68.png

0dcdde9b4b5a3763efc4617e31269936.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值