打字猴:1.70106642e+09
1701066420 还可以定义变量line[n]表示地址n中的字符串。例如,指令print(line[2])会显示输出:
1701066421
1701066422 print(“Hello, world!”)
1701066423
1701066424 此外,我们的编程语言中还包括loop指令(循环)。例如,下面的程序代码:
1701066425
1701066426 x=0
1701066427
1701066428 loop until x=4
1701066429
1701066430 {
1701066431
1701066432 print(“Hello, world!”)
1701066433
1701066434 x=x+1
1701066435
1701066436 }
1701066437
1701066438 会输出:
1701066439
1701066440 Hello, world!
1701066441
1701066442 Hello, world!
1701066443
1701066444 Hello, world!
1701066445
1701066446 Hello, world!
1701066447
1701066448 大括号之间的代码会反复执行直到循环结束条件(这里是x=4)满足。变量用作计数器——从0开始,每循环一次加1。增加到4时循环停止。
1701066449
1701066450 现在可以来看看自我复制程序了,程序完整展现在图8.2中。理解一段程序最好的办法就是手工推演,也就是一行一行跟踪程序的运行。
1701066451
1701066452 假设图8.2中的程序被加载到内存中,然后假设有人在计算机命令提示符后键入selfcopy,计算机就会开始执行程序selfcopy。译码器——操作系统的一部分——会将指令指针设为1,指向程序名。然后ip会下移,逐行执行各条指令。
1701066453
1701066454 在地址2处变量L被设为ip-1。而ip是当前执行指令的位置。因此当执行第2行时,ip设为2,L设为2-1=1。(注意虽然随着指令执行会不断变化,但L在重置之前会一直等于1直到其被重置。)接着会进入循环,直到line[L]等于字符串end。前面说了line[L]等于内存中地址L处的字符串。目前L等于1,line[L]等于字符串programselfcopy,不等于字符串end,因此循环不会停止。在循环中,会显示输出line[L],并将L加1。最初,L=1,显示输出program selfcopy;然后L被置为2。
1701066455
1701066456
1701066457
1701066458
1701066459 ▲图8.2 自我复制的程序
1701066460
1701066461 现在,line[L]指的是程序第二行,即L=ip-1,仍然不等于end,因此循环会继续。这样程序就会被逐行输出。尤其有意思的是第5行:当L=5时,执行第5行,指令print(line[L])会显示输出其自身。当L=9时,line[L]等于end,循环终止。这时已经显示输出了1—8行。指令指针指向第8行(紧跟在循环后面的指令),执行时显示输出字符串“end”结束自我复制。在这个程序中自我复制的本质,是用两种方式来使用内存中的信息:既作为执行的指令,又作为这些指令使用的数据。正是对信息的双重使用让我们得以避开前面尝试自我复制程序时遇到的那种无穷反复。
1701066462
1701066463 复杂 [:1701064766]
1701066464 自我复制程序的深层意义
1701066465
1701066466 信息的双重使用是哥德尔悖论的核心,他的自指句子“这个命题是不可证的”体现的正是这一点。
1701066467
1701066468 理解这个需要耍点把戏。首先,请注意这个句子同其他句子一样,可以从两个角度来看:①视为句子中包括的文字、空格符和标点组成的字符串;②视为字符串所代表的意义,同语言使用者的解读一样。
1701066469
[ 上一页 ]  [ :1.70106642e+09 ]  [ 下一页 ]