《论可计算数及其在判定上的应用》简单理解
剛剛拜讀了一本書, 《圖靈的秘密》. 該書介紹了圖靈的論文《論可計算數及其在判定上的應用》, 其指出: 一個擁有鉛筆, 紙和一串明確指令的人類計算者, 可以被看做是一種圖靈機. 那么圖靈機是什么呢? 是圖靈為了描述可計算數而引出的一個虛構的可以做一些簡單操作的計算機器. 盡管這個機器很簡單, 但圖靈斷言它再功能上等價與一個進行數學運算的人.
先提個小醒, 文章有些長, 而且還比較枯燥.
當然了, 那些數學證明并不是我關心的, 我關心的是這個圖靈機. 圖靈為了說明他的數學理論, 描述了一臺機器, 而這臺機器, 看過之后發現其實已經算是現代計算機的雛形了, 雖然他的出發點和發明計算機并不沾邊吧. 先簡單介紹一下這臺機器.
這是一個配有一條紙帶的機器, 紙帶由一個個方格隔開, 圖靈只使用其中相見的格子打印數據, 暫且稱之為數字格, 數字格之間的用來輔助計算. 大概就這么一個紙帶:
而這臺機器對操作的定義由一張狀態表來決定:
其中每個狀態(原文為: 格局)對應的符號不同, 會執行不同 的操作并切換的對應的下一個狀態. 可以將狀態類比成不同的函數, 再不同的選擇分支下執行不同的邏輯并調用不同的函數. 下面給出一些符合和操作的定義:
符號
- 0/1 : 指定字符
- Any: 非空的任意符號
- None: 空
- 留空: Any 和 None
- else: 狀態的其他符號都沒有匹配
操作
- R: 向右移動一格
- L: 想左移動一格
- P: 打印字符(P0, 打印0)
- E: 擦除當前格子內容
OK, 對圖靈這個簡單的機器介紹完畢, 是不是特別簡單. 一起跟著圖靈來看看, 他在這臺機器上都能夠做些什么操作吧.
打印序列010101…
先給出一格簡單的例子, 來看看這臺機器是如何運行的. 打印序列01010101..., 在前面加一個小數點, 這就是二進制的1/3了, 而將0和1的位置互換之后, 就是2/3了. 來看看圖靈是如何實現這一功能的.
| b | None | P0,R | c |
| c | None | R | e |
| e | None | P1,R | f |
| f | None | R | b |
對了, 圖靈的機器運行都是從狀態b開始的. 讓我們一起跟著狀態表走起來. (圖靈只使用相間的各自來打印數字, 數字格中間的用來輔助計算, 數字格不可更改)
1.展示紙帶的初始狀態
其中紅色方塊標記機器當前的掃描方格.
2.當前狀態: b, 打印0并向右移動一格, 切換狀態: c
3.當前狀態c, 向右移動一格, 切換狀態: e
4.當前狀態e, 打印0并向右移動一格, 切換狀態: f
5.當前狀態 f, 向右移動一格, 切換回狀態: b
此時, 切換回了初始的狀態, 然后周而復始的打印下去. 當然, 上述狀態是可以進行簡化的, 通過當前方格的不同符號, 可以進行不同的操作, 簡化后的狀態表:
| b | None | P0 | b |
| b | 0 | R,R,P1 | b |
| b | 1 | R,R,P0 | b |
簡單試一下, 簡化后的狀態實現的功能完全一樣.
當然, 這個例子實在太簡單了, 不過為了理解圖靈這臺機器, 還是有必要介紹一下的.
打印序列 001011011101111…
在這個序列中, 1的數量會依次加一, 也就是說要讓這臺機器再這個一維的紙帶上記住前面打印了多少個1. 那么圖靈是如何做到這一點的呢?
終于, 前面沒有用到的非數字格出場了, 它用來輔助打印.
| b | Pa,R,Pa,R,P0,R,R,P0,L,L | e | |
| e | 1 | R,Px,L,L,L | e |
| e | 0 | q | |
| q | Any | R,R | q |
| q | None | P1, L | p |
| p | x | E,R | q |
| p | a | R | f |
| p | None | L,L | p |
| f | Any | R,R | f |
| f | None | P0,L,L | e |
老規矩, 直接來走一遍狀態表, 邊走邊分析.
1. 當前狀態 b, 操作Pa,R,Pa,R,P0,R,R,P0,L,L, 切換狀態e
可以發現, 狀態b在初次執行之后, 就再也沒有出現過了, 所以可以將其形容為初始化的操作.
2.當前狀態e, 符號0,直接切換狀態: q
3.當前狀態q, 符號0, 操作: R,R, 切換狀態q
4.當前狀態q, 符號0, 操作: R,R, 切換狀態: q
5.當前狀態 q, 符號None, 操作: P1, L, 切換狀態p
可以看到, q狀態的操作就是向當前序列的尾部添加一個1.
6.當前狀態 p, 符號None, 操作: L,L, 切換狀態p
這不的操作就是向左移動到第一個不為空的非數字格. 省略一步, 結果:
7.當前狀態p, 符號a, 操作: R, 切換狀態: f
從這里可以看出來, p狀態其實是充當各個狀態之間的調度員角色的.
8.當前狀態f, 符號0, 操作: R,R, 切換到狀態f
這里, 可以觀察到, 狀態f的作用是向數字的結尾打印0, 然后左移兩格, 切換到e狀態. 跳過中間步驟:
**9.當前狀態e, 符號1, 操作: R,Px,L,L,L, 切換狀態e. **
簡單分析, e狀態的操作是在連續1的每一個右邊打印x, 之道遇到0, 切換到q狀態
10.當前狀態q, 符號0, 則向尾部添加一個1, 切換狀態p
**11.當前狀態p, 符號None **
通過前面分析, p狀態向左找到第一個不為空的非數字格, 在這里則是x. 然后會擦除x并切換到q狀態, 既向右打印1. q狀態執行完畢后的紙帶狀態如下:
此時會再次切換回p狀態, 向左找到a, 然后切換到f狀態, 向右打印一個0.
完美, 此時其實已經發現了, 圖靈的方法是在連續1的后面添加x標記, 每個x標記都對應一格末尾的1. 以此來獲得上一次打印1的數量.
至此, 這臺簡單的機器已經能夠記憶一些內容了.
數字遞增
至此, 圖靈這臺機器雖然已經能夠打印一些復雜的內容了, 不過都是一些簡單的重復工作, 還沒有能夠稱之為計算的東西. 為了引出后面的計算, 先來實現一個簡單的數字遞增.
這是一個不符合圖靈約定的機器, 加在這里只是為了引出計算. 而且他的最高位數字向左打印. 來看一下這個狀態表:
| b | None | P0 | i |
| i | 0 | P1 | r |
| i | 1 | P0,L | i |
| i | None | P1 | r |
| r | None | L | i |
| r | Any | R | r |
這個簡單的例子就不再展開步驟了, 可以動手試一下, 它確實實現了數字的遞增. 從這里能夠看出使用二進制的好處, 如果使用十進制相同的功能, 則i狀態需要列出0-9始終狀態十種狀態, 而二進制則只需要兩種.
計算2\sqrt{2}2?
好了, 論文中首個可以稱為計算的例子來了. 2\sqrt{2}2?是一個無限不循環小數.
先來介紹一下在計算2\sqrt{2}2?時涉及的數學知識. 首先, 2\sqrt{2}2?一定是介于1-2之間的一個小數. 二進制的2\sqrt{2}2?前十位是: 1.011. 如何確定下一位是0還是1呢? 方法聽上去很簡單, 先假設下一位是1, 然后讓這個 n 位數與自身相乘, 若結果是2n-1位, 則說明結果小于2, 下一位是1. 若結果是2n位, 則大于2, 下一位是0. 這個很好證明, 可以自己動手算一下.
而一個 n 位數與自身相乘, 需要將其中的每一位與每一位相乘, 共需要計算n*n次. 產生n個局部乘積, 然后將局部乘積進行相加得到結果.
而圖靈在計算時, 使用了稍有不同的方法進行乘法計算, 在運算中維護一個過程和, 每一位的相乘結果加到這個過程和中. 當然, 每一個位與位的乘積, 并不是加到過程和的最低位, 而是加到中間的某個位置上.
二進制的乘法很簡單, 1*1=1, 其他情況都是0. 而乘積加到過程和的哪一位, 如果右起第2位(從0開始)乘以第3位, 則加到結果和的第2+3=5位上. 先說明, 在下方的過程和計算中, 過程和的最低位在左側, 與數字格的順序相反, 應該是為了簡化計算過程吧.
來一起看看圖靈是如何實現這個功能的呢? 這次就不直接上狀態表了, 這個表有點長, 就拆成多個放到分析中了. 如果有感興趣的, 將下方所有狀態合起來就是完整的狀態表了.
| begin | None | Pa,R,P1 | new |
為了方便介紹, 我們就不從頭跑一遍了, 太費篇章. 我們就從中間位置開始來看一下他的計算過程, 具體過程可以自己跟著狀態走一遍. 假設現在已經計算出了三位1.01.
其中?標識當前需要計算的下一位, 并沒有實際出現在紙帶上. 每次計算新的一位, 都會調用new狀態將掃描格重置到最左邊的數字上:
| new | a | R | mark_digits |
| new | else | L | new |
假設此時, 紙帶的狀態:
現在對各個數字位進行標記.
| mark_digits | 0 | R,Px,R | mark_digits |
| mark_digits | 1 | R,Px,R | mark_digits |
| mark_digits | None | R,Pz,R,R,Pr | find_x |
很簡單, 在所有已知位后面都標記x. 未知位標記z, 然后在過程和的最低位打印r.
當前狀態: find_x
| find_x | x | E | first_r |
| find_x | a | find_digits | |
| find_x | else | L,L | find_x |
| first_r | r | R,R | last_r |
| first_r | else | R,R | first_r |
| last_r | r | R,R | last_r |
| last_r | None | Pr,R,R,Pr | find_x |
r是過程和的最低位, 可以將其看做0. 接下來的步驟, 會將每一個x都對應的打印兩個r. 也就是說, 現在數字一共4位(包括?, 其為1). 然后打印了7個 r (2n-1). 根據之前的推測, 若結果需要新的一位, 則值為0, 否則為1.
當前狀態: find_digits
| find_digits | a | R,R | find_first_digit |
| find_digits | else | L,L | find_digits |
| find_first_digit | x | L | found_first_digit |
| find_first_digit | y | L | found_first_digit |
| find_first_digit | z | L | found_second_digit |
| find_first_digit | None | R,R | find_first_digit |
如果未知位是1, 那么過程和7位就夠用了, 否則未知位就是0. 現在, 已經有了都是0的7位過程和, 可以開始做乘法運算了.
現在, 開始準備首次的位與位相乘了. 為了記錄當前是那兩位在做乘法運算, 使用x, y, z進行標記. 其中x標記與y標記做乘法運算, 若自身相乘, 則標記為z. 先通過find_digits 回到第一個非數字格. 然后通過find_first_digit 跳到第一個做乘法運算的數字格. 并根據標記的不同調用不同的方法.
當前狀態: found_second_digit
| find_second_digit | x | L | found_second_digit |
| find_second_digit | y | L | found_second_digit |
| find_second_digit | None | R,R | find_second_digit |
| found_first_digit | 0 | R | add_zero |
| found_first_digit | 1 | R,R,R | find_second_digit |
| found_second_digit | 0 | R | add_zero |
| found_second_digit | 1 | R | add_one |
| found_second_digit | None | R | add_one |
這里可以看到, 若找到的數字是0, 則直接加0, 因為相乘后的結果必是0. 若相乘之后的結果是1, 則向過程和加1.
若找到的第一個數字是1, 則轉換去尋找第二個數字.
當前狀態: add_one
| add_zero | r | Ps | add_finished |
| add_zero | u | Pv | add_finished |
| add_zero | else | R,R | add_zero |
| add_one | r | Pv | add_finished |
| add_one | u | Ps, R,R | carry |
| add_one | else | R,R | add_one |
雖然給過程和中加0并不會對其值造成改變, 但是不管想其中加入了什么, 機器都需要對其進行一些維護. 之前說過, 過程和的r表示0, 其實s, t也表示0, 對應的, u, v, w 則表示1. 為什么需要多個字母來表示同一個數字呢? 是為了下一次加法運算時, 用來標識當前數字已經參與過運算, 應該將結果加到下一位上.
add_zero會將它找到的第一個r標記為s, 或者找到的第一個u標記為v. 然后結束加法操作.
而向過程和中加一, 則需要更多的操作, 畢竟數字已經變了嘛, 而且還需要處理進位. 將找到的第一個r變成v(0變成1), 或者找到的第一個u變成s(1變成0)并同時處理進位.
當前狀態: add_finished
| add_finished | a | R,R | erase_old_x |
| add_finished | else | L, L | add_finished |
| erase_old_x | x | E,L,L | print_new_x |
| erase_old_x | z | Py,L,L | print_new_x |
| erase_old_x | else | R,R | erase_old_x |
| print_new_x | a | R,R | erase_old_y |
| print_new_x | y | Pz | find_digits |
| print_new_x | None | Px | find_digits |
| erase_old_y | y | E,L,L | print_new_y |
| erase_old_y | else | R,R | erase_old_y |
| print_new_y | a | R | new_digit_is_one |
| print_new_y | else | Py,R | reset_new_x |
此時, 加法結束了, 需要移動x, y, z標記, 來標識下一對需要相乘的數字. 簡單設想一下, 若只有一個z則將其標記為y并將左側標記為x即可. 若一個x一個y, 則將x左移一位, 但是當x到達最高位時, 需要將x重置到最低位, 同時左移y. 當y到達最左側的時候, 計算結束.
當前狀態: find_digits
現在, 計算又回到了最初的狀態, 可以開始進行新一輪的計算了. 這次相乘的結果1*1=1, 再次向過程和中加一. 結果:
繼續執行后, 需要下面幾個狀態(下面為每次回到find_digits狀態的紙帶情況)
| reset_new_x | None | R,Px | flag_result_digits |
| reset_new_x | else | R,R | reset_new_x |
| flag_result_digits | s | Pt,R,R | unflag_result_digits |
| flag_result_digits | v | Pw,R,R | unflag_result_digits |
| flag_result_digits | else | R,R | flag_result_digits |
| unflag_result_digits | s | Pr,R,R | unflag_result_digits |
| unflag_result_digits | v | Pu,R,R | unflag_result_digits |
| unflag_result_digits | else | find_digits |
可以看到, 當x重置的時候, 下一次位與位相乘的結果需要加到過程和的第二位上, 因此, 需要對過程和的內容做少許修改: 第一個s或v變成t或w, 剩下的s或v變成r或u. 為了下一次計算的時候, 能夠將結果加到對應的位置上, 就是下一次相乘結果的相加位要向后一格, 在做加一操作的時候, 只識別r, u, 所以之后的標識符還需要重置.
操作已經簡單的走了, 是時候將所有狀態放出來了.
| carry | r | Pu | add_finished |
| carry | u | Pr,R,R | carry |
| carry | None | Pu | new_digit_is_zero |
| new_digit_is_zero | a | R | print_zero_digit |
| new_digit_is_zero | else | L | new_digit_is_zero |
| print_zero_digit | 0 | R,E,R | print_zero_digit |
| print_zero_digit | 1 | R,E,R | print_zero_digit |
| print_zero_digit | None | P0,R,R,R | cleanup |
| new_digit_is_one | a | R | print_one_digit |
| new_digit_is_one | else | L | new_digit_is_one |
| print_one_digit | 0 | R,E,R | print_one_digit |
| print_one_digit | 1 | R,E,R | print_one_digit |
| print_one_digit | None | P1, R,R,R | cleanup |
| cleanup | None | new | |
| cleanup | else | E,R,R | cleanup |
其中carry的操作就是進位操作, 當遇到符號1時, 將其改為0繼續進位, 當遇到符號0的時候, 則改為1, 結束. 若遇到空內容, 說明計算產生第8位了, 則未知位必為0, 直接結束計算.
從上面看到, 還有一種結束情況就是y走到頭了, 這時沒有產生進位, 說明未知位為1.
剩余的幾個狀態就一帶而過了, 未知位是1, 未知位是0, 以及cleanup清理所有過程和的內容.
整個乘法會以兩種情況結束:
至此, 已經完成了計算2\sqrt{2}2?的操作. 這個狀態可以周而復始的一直計算下去. 不再繼續延時了, 感興趣的可以自己按照上面的狀態表算一遍. 看了上面命名的狀態, 有沒有覺得和函數很像呀.
其實其原理并不復雜, 就是進行0和1的簡單嘗試, 然后根據結果的大小來決定后一位是什么內容. 但我還是被圖靈能夠在一維的紙帶上實現的操作折服了.
方法集
看了上面的內容, 有沒有覺得少了點什么? 那一個個的不就是函數嘛.而圖靈下一步要做的, 就是要組建一格常用表集, 作為基礎來搭建一些更為復雜的表. 更形象的說法就是封裝函數. 同時, 函數的封裝也方便他后面構建更大的程序. 關于函數的概念就不在贅述了, 天天用的也不少了. 就給出圖靈的表達形式, 大家自然能夠看懂.
回看一下上面的new_digit_is_zero和new_digit_is_one兩個函數, 函數化之后的標識:
| print_digit(A) | 0 | R,E,R | print_digit(A) |
| print_digit(A) | 1 | R,E,R | print_digit(A) |
| print_digit(A) | None | P(A),R,R,R | cleanup |
很好理解哈, 就不解釋了. 同時, 其參數也可以傳遞狀態. 將這個基礎表稱之為骨架表. 可以看的出來, 所有的骨架表都可以轉換成不帶參數的形式. 到這里, 其實和現在的函數式編程思想已經很接近了有木有.
舉個栗子:
| f(S, B, a) | α | L | f1(S, B, a) |
| else | L | f(S, B, a) | |
| f1(S, B, a) | a | S | |
| None | R | f2(S, B, a) | |
| else | R | f1(S, B, a) | |
| f2(S, B, a) | a | S | |
| None | R | B | |
| else | R | f1(S, B, a) |
其中 α 用來標識開始.
來看一下這個骨架表是做什么用的? 簡單分析一下:
-
f 函數: 向左找到標識符α, 然后轉到 f1函數
- 將掃描格進行定位
-
f1函數: 向右找, 若找到 a, 執行 S 函數, 空格向右轉到 f2函數, 否則繼續向右尋找
- 找到向右的第一個 a, 執行 S 函數
-
f2函數: 向右找, 若找到 a, 執行 S 俺叔, 空格向右執行 B 函數, 否則向右轉到 f1函數
- 找到向右的第一個 a, 執行 S 函數
- 若找到連續兩個空格, 執行 B 函數(與 f1函數配合, 識別連續的兩個空格)
可以看出, f 就是 find, 他會尋找 a(也是參數), 若找到, 執行 S, 沒找到則執行 B.
再來看一個栗子:
| e1(S) | E | S | |
| e(S, B, a) | f(e1(S), B, a) |
看這個骨架表. 函數 e1 的作用是將符號擦除, 然后轉到 S 狀態.
那么相對的, e 函數的作用是, 向右找到第一個 a, 若找到了則擦除并轉到 S, 若沒有找到, 轉到 B. 同時, 圖靈還允許一個函數同時接收不同個數的參數(想到了什么? 函數重載)
| e(B, a) | e(e(B, a), B, a) |
這個兩個參數的e函數是不是有點皮了. 來分析, 三參數的e, 作用是找到 a 符號并擦除, 然后轉到 S. 再看兩參數的e函數, S 是什么? 還是他自己, 繼續找一個 a 符號并擦除, 直到擦除調所有的 a.
也就是說, 這個函數實現的功能是, 擦除所有的 a, 然后轉到 B. 從這可以看出, 圖靈的思想對現在的編程提供了一定思路, 已經有函數的嵌套調用了, 膜拜了.
再來看一些定義的基礎庫, 來幫助理解圖靈的這個概念.
找到出現的最后一格 a
函數 f 從左向右查找, 函數 g 從右向左找.
| g(S) | Any | R | g(S) |
| None | R | g1(S) | |
| g1(s) | Any | R | g(S) |
| None | S | ||
| g1(S, a) | a | s | |
| else | L | g1(S, a) | |
| g(S, a) | g(g1(S, a)) |
其中單參數的函數 g 和單參數的函數 g1配合, 將掃描格移到最右側.
在結尾打印
| pe(S, b) | f(pe1(S, b), S, α) | ||
| pe1(S, b) | Any | R,R | pe(S, b) |
| None | Pb | S |
其中, 這個函數有一個假設, 就是最左側有兩個連續α, f 函數先將掃描格移動到最左側α, 然后右移一格開始尋找, 這時當前格就是α.
在結尾打印兩個字符
| pe2(S, a, b) | pe(pe(S, b), a) |
直接先在結尾打印 a, 然后在在結尾打印 b
增強 find 函數
f 函數在找到所需字符后, 將掃描格向左或向右移動.
| l(S) | L | S |
| r(S) | R | S |
| fl(S, B, a) | f(l(S), B, a) | |
| fr(S, B, a) | f(r(S), B, a) |
復制字符
找到用 a 標記的字符, 復制到結尾. 然后調用 S 函數.
| c(S, B, a) | fl(c1(S), B, a) | |
| c1(S) | β | pe(S, β) |
這里有一個特殊的地方, c1函數中, 符號β表示掃描到的字符. 當然也可以將不同的字符進行排列(可能只有0或1).
復制并擦除
| ce(S, B, a) | c(e(S, B, a), B, a) |
| ce(B, a) | ce(ce(B, a), B, a) |
其中三參數的ce, 會找到 a 標記的符號, 并復制到結尾. 然后調用e擦除 a 標記. 擦除后執行第一個參數的狀態. 而在兩參數的ce中, 傳遞過期的第一個參數是它自己. 就是說, 兩參數的ce會將所有 a 標記的符號復制, 同時擦除 a 標記, 最終轉到 B.
(在之前打印’001011011101111…'的例子中, 就可以使用這個函數對1進行復制)
看到這里已經發現了, 圖靈機令人咋舌的效率問題. 為了執行以此復制并擦除, 函數 c 會先調用 f 遍歷一遍(f 函數會先回到開頭的位置)進行復制操作, 然后再調用 f 進行遍歷并將其擦除. 而復制擦除下一個字符, 又要重復這些操作. 如果在第一次找到的時候, 就順手擦除, 然后再進行復制, 豈不更好.
不過, 想必圖靈在當時并沒有考慮效率的問題, 或者說他并不關心效率的好壞, 畢竟連這臺機器都是想象出來的. 現在, 圖靈已經可以構建一格函數庫了, 類似與現在的系統庫, 想必能夠構造更為強大的機器了.
數字化
接下來, 圖靈對他的表格進行了重新定義. 他先是證明了所有狀態都可以拆解成如下所示的三個狀態:
| qi | Sj | PSk, L | qm | N1 |
| qi | Sj | PSk, R | qm | N2 |
| qi | Sj | PSk | qm | N3 |
其中 Sk 用來表示符號. 規定:
- S0 : 表示空格
- S1 : 表示0
- S2 : 表示1
- 其他: 一些自定義符號
其中的操作是:
- N1 : 打印并左移
- N2 : 打印并右移
- N3 : 打印
疑問, 改成這樣真的能夠表示之前的所有操作么? 舉例一下 :
- 擦除操作: 既打印空格. PS0
- 左移操作: 既打印格子原本的符號.
而之前的一些較長的操作, 通過拆解也可以拆成這樣的基本形式. 然后, 圖靈定義了這么一格五元組:
qiSjSkLqm 用來直接表示上方的 N1 . 無用說也能和上面的表格對上吧. 有沒有想到圖靈要做什么? 這里每一個五元組, 都對應一個操作, 如果將多個五元組連起來, 并用分號隔開, 是不是就能完整的描述一個程序了.
至此, 他的狀態表已經經過了一次轉換, 變成了下標的形式. 接下來, 圖靈要把下標去掉. 替換:
- qi -> D 后面 i 個 A
- Sj -> D 后面 j 個 C
如此一來, 他的機器就只剩下以下幾個字符: D, A, C, L, R, N, ;. 其中N表示不移動. 圖靈將這樣的描述稱為標準描述.
再然后, 圖靈將僅存的這7個字符, 用1-7的數字來表示. 既: 1(A), 2?, 3(D), 4(L), 5?, 6(N), 7(😉. 那么, 將得到一個完全由數字組成的完成程序. 而這些數字連起來, 就是一個比較大的整數, 也就是說, 圖靈用一個整數來完全表示了他的機器. 這個數字被圖靈稱為描述數.
也就是說, 一個描述數可以唯一確定一個程序, 而一個程序可以對應多個描述數(因為狀態的順序是可以隨意更換的). 同時, 這也說明通過枚舉所有的整數, 可以得到所有可能的計算序列.
其實與現在的程序有著異曲同工之妙, 現在的程序也不過是一串二進制的數字.
可編程通用機
接下來, 圖靈描述了一個可編程的通用機器, 將程序1的描述數放到紙帶的開頭, 機器 A 通過讀取并完全復刻所有格局來實現程序1的功能. 這臺機器可以通過讀取不同的輸入紙帶, 來實現不同程序的功能.
同時, 圖靈證明了這樣一個機器的可行性. 現在, 假設需要執行的程序是之前的交替打印0和1的程序, 其狀態表如下:
| b | None | P0 | b |
| 0 | R,R,P1 | b | |
| 1 | R,R,P0 | b |
轉換成通用格局之后:
| q1 | S0 | PS1,R | q2 |
| q2 | S0 | PS2,R | q1 |
很簡單, 打印0然后打印1, 交替進行. 將通用格局轉換成可描述符號:
- q1S0S1Rq2: DADDCRDAA
- q2S0S2Rq1: DAADDCCRDA
輸入紙帶如下所示(一行顯示不下, 但他還是一維紙帶哦):
每一條指令由五個連續部分組成:
接下來的證明過程, 就有些超出我的理解了, 感興趣的朋友可以自行鉆研一下, 我是看了好久, 也沒搞懂.
至此, 圖靈的這臺機器, 其實已經有了現代計算機的雛形了. 而我, 也被這幾十年前偉大的思想折服了. 牛批…
同時, 圖靈的論文后面還使用這臺通用機器進行了一些證明, 不過, 那并不是我所關心的內容.
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的《论可计算数及其在判定上的应用》简单理解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: caffe初体验
- 下一篇: vs简易计算机等于号代码,等于(=)vs