您好,登錄后才能下訂單哦!
本篇內容主要講解“如何理解數學上的閉包概念及與編程的關系”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“如何理解數學上的閉包概念及與編程的關系”吧!
閉包在數學上是一個比較抽象的概念, 來自于抽象代數, 因此這里不打算直接給出它的定義, 否則大家看了估計還是一頭霧水, 為便于理解, 還是先從具體的例子出發, 最后才給出它的定義.
我們先考察一個很簡單的例子, 就是加法在自然數集合中的操作及其結果.
首先, 自然數集這個很好理解, 就是0, 1, 2, 3..., 這些整數的集合, 當然需要注意的一點是它是一個無窮的集合.
然后是加法這個操作, 我們也很熟悉, 它需要兩個操作數, 從剛才的自然數集合中任意取出兩個數, 然后執行加法操作:
比如, 1 + 2, 3 + 5, 6 + 4 等等
然后這些加法操作會有一個結果, 比如 1 + 2 = 3, 3 + 5 = 8, 6 + 4 = 10 等等, 當我們觀察這些結果, 比如 3, 8, 10 等等時, 不難發現它們也還是屬于自然數集合.
說到這里, 你可能會想, 這不是顯而易見的嘛, 感覺像是說了一堆廢話! 先別急著下定論.
至此, 我們就可以初步給出閉包的定義, 首先有一個集合(自然數集合), 然后有一個操作(加法操作), 這個操作需要集合中的兩個元素, 最后操作的結果仍然屬于這個集合.
因為結果仍然屬于這個集合, 我們就說, 自然數集合對于加法操作來說是封閉的(closed).
這個是針對結果來說的, 也就是無論你怎么操作來操作去, 結果都還在集合內, 有點孫悟空怎么翻筋斗也逃不出如來佛手掌心那種感覺.
自然數集合在加法這樣一種操作下是封閉的, 我們就說它滿足(satisfy)一種閉包性質(clousre property).
更一般化的說, 一個集合被認為是滿足一種閉包性質, 如果它在一個(或一系列)操作下是封閉的.
A set that is closed under an operation or collection of operations is said to satisfy a closure property.
上面的定義涉及到一個或一系列操作, 下面就說說另一個操作, 比如乘法, 同樣還是自然數集合, 隨便取兩個數, 然后乘起來:
比如, 2 × 3, 3 × 7, 5 × 4 等等.
然后也會有一個結果, 比如 2 × 3 = 6, 3 × 7 = 21, 5 × 4 = 20 等等, 當我們觀察這些結果, 比如 6, 21, 20 等等時, 不難發現它們也還是屬于自然數集合.
因此, 根據前面的定義, 我們可以說, 自然數集合對于乘法操作來說也是封閉的(closed).
畢竟來說, 乘法在某種意識上講也是一種加法, 因此自然數集合對其封閉也就不難理解了.
自然數集合對于加法操作來說是封閉的(closed), 同時對于乘法操作來說也是封閉的(closed), 因此, 可以說它在一系列操作(加法及乘法)下都是封閉的.
也即是一個集合可以不僅對一個操作是封閉的, 它還可能對很多操作都是封閉的.
說完了加法和乘法, 估計有些同學已經不耐煩了, 說, 這有啥稀奇的呢? 難道有什么操作是不封閉的嗎? 下面就來說說再另一個操作, 減法, 然后我們會發現, 事情會有一些變化.
如果草率地去看, 還是針對自然數集合來說, 隨便取兩數, 然后執行減法操作:
比如, 3 - 2, 7 - 4, 5 - 1 等等;
然后也會有一個結果, 比如 3 - 2 = 1, 7 - 4 = 3, 5 - 1 = 4 等等, 當我們觀察這些結果, 比如 1, 3, 4 等等時, 不難發現它們也還是屬于自然數集合.
從以上來看, 我們似乎也可以說, 自然數集合對于減法操作來說同樣也是封閉的(closed).
但只要我們多考察一些情形, 比如 2 - 4, 3 - 6 等等, 就會發現, 不對勁了, 2 - 4 = -2, 3 - 6 = -3, 像 -2, -3 這些結果它們并不屬于自然數集合!
在古代, 人們的認知能力還很弱時, 面對像 2 - 4 這么騷氣的操作時, 干脆就像鴕鳥把頭埋進沙子里一樣, 對其視而不見了, 人們認為這樣的操作是沒有意義的!
于是, 自然數集合對于減法操作來說并不是封閉的. 但如果我們擴大自然數集合, 變成整數集合, 它包含了負整數集合, 0 和 正整數集合.
這時候, 對于一個整數集合而言, 則無論你怎么去取數進行減法操作, 結果總是還在這個整數集合中.
又一次的, 孫悟空怎么翻筋斗也逃不出如來佛手掌心, 這是個更大的手掌心!
于是, 雖然自然數集合在減法的操作下不是封閉的, 但一旦擴大到整數集合, 我們又可以說, 整數集合對于減法操作是封閉的.
另一種情形則是, 對一個有限的集合而言, 比如只有一個元素 0 的集合, 表示為 { 0 }, 我們也照樣可以說, 它對于加法, 乘法和減法都是封閉的, 因為 0 + 0 = 0, 0 × 0 = 0, 0 - 0 = 0, 結果無論怎么搞都還是 0, 因此也是封閉的. 這個例子中沒有擴大集合的范圍, 甚至是相反, 縮小了集合的范圍, 也能得出封閉的性質, 當然這就屬于比較特殊的情況了.
前面提到的一個閉包的定義是指集合滿足的一種閉包性質, 對于閉包還有另外一種定義.
當一個集合 S 在某些操作下不是封閉的,
比如自然數集合對于減法操作不是封閉的.
我們可以找到一個包含 S 的最小集合使得操作是封閉的,
比如, 可以找到 整數集合 這個包含 自然數集合 的最小集合, 它對于減法操作是封閉的.
那么, 這個最小的集合就叫做 S 集合(針對那些操作而言)的閉包(closure).
整數集合就是自然數集合(針對減法操作而言)的閉包.
具體的英文定義如下:
When a set S is not closed under some operations, one can usually find the smallest set containing S that is closed. This smallest closed set is called the closure of S (with respect to these operations)
這個定義跟閉包性質的定義有差異, 但兩者還是有緊密關系的, 只不過是說法的側重點不同, 但都是圍繞著操作結果的封閉性去說的.
整數集合對于加法, 乘法和減法都是封閉的, 但如果繼續引入其它操作, 比如除法, 那么新的問題又會來了, 雖然像 6 ÷ 2, 10 ÷ 5 等整除的情形, 結果還在集合中, 但更多的諸如 2 ÷ 3, 5 ÷ 8 結果就不在集合里面了.
此時如果想讓除法操作封閉, 還得繼續擴展集合到比如有理數集合.
此外還得施加一個限制, 除數還不能為 0.
而對于有理數集合, 當繼續擴大操作時, 比如引入了開方運算, 很多結果又不是封閉的了, 這時得擴大到無理數集合; 而即便是到了無理數集合, 對于負數的開平方依然是束手無策的, 這時就需要進一步的擴大到復數集合了...
顯然的, 當引入越來越多的操作, 想繼續的保持封閉性就很困難了.
至此, 我們已經說完了數學上的閉包這一概念, 自然也只是蜻蜓點水地說一下, 讓大家有個概念而已, 更深的咱們也不懂, 也不打算去涉及, 畢竟太艱深了.
通過以上的介紹, 相信大家對數學上的閉包這一概念多少也有了一些了解, 但很多人可能會問, 去知道這些干啥呢? 對我們編程似乎也沒啥用. 而前面一開始也說了, 這里談的閉包還不是編程界通常談論的那個閉包, 那這里談論的這個數學上的閉包對于我們的編程語言到底有什么影響呢?
怎么說好呢, 要說沒有影響恐怕是不可能的, 但如果說有多少大的影響恐怕很多人又不認同了, 問題就在于這些影響往往是非常基礎性的, 以至于我們不覺得這算什么影響.
舉個非常簡單的例子, 我們在編程中很可能隨手就寫出了這樣的表達式:
2 + 4 + 5
而從不去問到底為什么, 甚至說這為什么是可能的, 我們覺得這些似乎是天經地義, 不值一提的.
但從閉包的角度去看, 2 + 4 + 5 之所以成為可能, 是因為 2 + 4 的結果仍然屬于集合之內, 才因此可以繼續參與下一次的操作.
當我們例舉另外的例子, 比如另一個表達式:
(3 > 2) + 1
情況就有點微妙了. 對于有些編程語言而言, 這樣的操作仍然是可行的, 但其實是因為包含了一種隱式的轉換; 而對于另外的一些編程語言來說, 這可能就是語法錯誤了.
從閉包的角度去看, 3 > 2 這個操作的結果并不屬于數的集合, 而是一個只有兩個有限元素的 boolean 集合: {true, false}.
因為這個操作的結果并不是一個數, 所以后續的操作其實就沒有意義了.
比如 true + 1, 或者是 false + 1 都是沒有意義的了.
有些編程語言之所以能夠繼續操作下去, 是因為內部做了隱式轉換, 比如把 true 轉為 1, false 變為 0, 所以繼續執行的其實是 1 + 1 或者 0 + 1.
有些語言限制會比較嚴格, 比如 java, 你寫這樣的語句是要報錯的:
if (age = 60) { // 可以退休了 }
這里的一個陷阱就是, 單個的等號是一個賦值的操作, 而不是比較, 比較是用兩個等號 == 這樣:
if (age == 60) { // 可以退休了 }
這樣寫的 java 程序才能編譯通過, 但有的語言兩種寫法都能編譯, 但第一種情況實際會變成:
if (60) { // 可以退休了 }
但 if 其實要求的是一個 boolean 集合的操作數, 而此刻會執行一次轉換, 一般而言, 0 會轉成 false, 其它則是 true, 所以 60 就轉換為 true, 最后語句實質變成了:
if (true) { // 可以退休了 }
這樣一來, 整個判斷就完全多余了, 結果總是為真, 里面的語句始終都能執行, 在很多情況下, 這就是一個程序的 bug 了.
可見, 不嚴格的遵循閉包性質可能會給我們帶來麻煩; 另一方面, 設計良好的閉包性質有可能帶給我們便利.
比如說, 有的語言允許數組的元素還可以是數組, 這就給很多的操作帶來了很多方便, 這其實是閉包性質的一個體現.
而有的語言則不允許這樣, 數組的元素只能是其它元素, 但不能是數組, 這就削弱了語言的表達能力, 進而在編程中給我們帶來不便.
又比如, 對于很多語言來說, 對象的屬性可以繼續是對象, 又或者說, map 的元素還可以是另一個 map, 這樣一來, 我們就可以嵌套地表達很多復雜的數據結構, 而對它們的操作又可以比較簡化, 因為操作的結果還在集合內, 就可以反復運用同一種操作去操作它.
舉個例子來說, 一顆樹的節點可以是一個葉子節點, 還還可以是一棵子樹, 對于文件夾及里面的文件及(或)文件夾而言就是這么一種情形, 因此可以用同一個操作遞歸地遍歷所有的節點.
而上述這些, 往深了說, 其實都是都是閉包性質的體現, 因為這些性質的存在, 才使得這些成為可能.
對于我們的編程實踐來說, 某種組合數據對象的操作滿足閉包性質, 那就是說,通過它組合起數據對象得到的結果本身還可以通過同樣的操作再進行組合.
閉包性質是任何一種組合功能的威力的關鍵要素, 因為它使我們能夠建立起層次性的結構, 這種結構由一些部分構成, 而其中的各個部分又是由它們的部分構成, 并且可以如此繼續下去.
到此,相信大家對“如何理解數學上的閉包概念及與編程的關系”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。