淺談邏輯:編程中最重要的基礎

“英語不好能不能學編程?”

“編程是不是對數學要求很高?”

時不時會在公*號後臺收到類似的疑問,即:數學/英語是否是學編程先決條件?

我覺得這個問題有點像,身高不高能不能打籃球一樣。雖然對於職業籃球運動員來說,身高是非常關鍵的因素,但對於普通籃球愛好者,甚至一個籃球相關從業人員來說,這並不是非要不可的條件。放到編程上,數學和英語都很重要,但:

  1. 在入門階段,你完全不用在意這些,照着一本教程好好跟着模仿就行
  2. 對於大部分的日常開發來說,中學程度的數學和英語水平已經可以應付
  3. 和身高這種先天條件不同,英語和數學是可以通過學習提高的,哪裏不足補哪裏唄。“以大多數人的努力程度之低,根本輪不到拼天賦。”你能長期堅持背背單詞,看看書,就足以提升自己。總是把XX不好掛在嘴上恐怕更多是在給自己找藉口。

不過,有一項能力,確實是在學習編程初期就需要足夠重視的。然而這一點,很多教程不會專門強調,相關書籍也往往假定你已經掌握,以至於很多學習者並沒有意識到自己在此方面的薄弱,爲之後的學習留下隱患。我要說的就是:

邏輯

某種角度來說,邏輯可部分算作是數學,在高中數學課本中就有相關內容。這部分內容也恰好是我們學編程時最需要了解的基礎。

一、布爾代數

真(1)、假(0)兩種狀態,以及與(and)、或(or)、非(not)三種基本運算組成。布爾代數看似簡單,卻與數字電路中開和關兩種狀態相對應,是計算機的邏輯基礎。你可能聽說過,電腦上的一切在內部都是由0和1所表示,那換句話說,計算機的所有行爲,本質都是由布爾邏輯所實現的。

在編程語言中,布爾類型(bool)也是極爲重要的存在。沒有它,我們就做不了條件判斷,也就無從控制程序的執行。Python 的 if、while 語句都必須依賴布爾類型作爲判斷條件

因此,即使你不想深入學習邏輯,布爾代數的基本規則也是無論如何必須瞭解的。簡單來說,就是下面這張“真值表”:

這些基本規則又會組合出更復雜的邏輯,比如:

not (p or q) 等價於 (not p) and (not q)

(示例:“不是管理員或者會員”相當於“不是管理員且不是會員”)

實際開發中面臨的邏輯判斷複雜多樣,但歸根結底還是會轉化到最基本的這幾個規則上。

思考題1:如何用邏輯語言表示“通過活動註冊的新用戶或者充值超過100元的老用戶,內部人員除外

二、命題邏輯

真值唯一的陳述句叫做命題,不能分解成更簡單的命題叫做原子命題。比如,“1+1=2”是原子命題,“所有貓都是白的”是原子命題(假命題),“存在外星人”也是原子命題(雖不能判斷真假,但結果必然唯一)。命題和邏輯運算相結合,又會產生更復雜的邏輯。

比如充分必要條件

如果命題p必然推出命題q,那麼p就是q的充分條件,q就是p的必要條件,記作 p→q。

比如漢樂府的詩句“山無棱,天地合,乃敢與君絕”,用邏輯語言表達是怎樣?

(山無棱 and 天地合) → 與君絕?

想一想是不是不大對勁?根據語義來看,“山無棱”、“天地合”是“與君絕”的必要條件,如果“與君絕”爲真,那必然存在“山無棱”和“天地合”,反過來卻未必。所以正確的邏輯是:

與君絕 → (山無棱 and 天地合)

再比如三段論

①不掌握基本的邏輯知識就無法學好編程

②Python是一種編程語言

所以,學好Python需要掌握基本的邏輯知識

一個大前提加上一個小前提,可以推導出一個結論。這是日常使用最多的論證形式,看似簡單,但也總有人在這上面犯糊塗。舉個錯誤的例子

①有錢人都用 iPhone XS Max

②我用 iPhone XS Max

所以,我是有錢人

這些邏輯關係、推導過程與程序中的邏輯結構息息相關。如果你對此不能保持思路清晰,寫出的代碼很可能與預期有出入,或是在一些特殊情況下存在漏洞。

思考題2:一個每天簽到領獎的小功能,在每天的11~13點和18~20點開放,普通用戶每天可以領取一次,會員用戶可以在每個時段分別領取一次。如何實現這段程序的邏輯結構?(我時常拿這個作爲面試題,很多人都不能在短時間內給出正確的答案)

三、歸納

有時候,我們並不能通過邏輯推導出必然的結論,但仍然可以通過一系列的經驗和已有結論,找出其中基本遵循的規律

比如:

①X團隊歷來給所有成員都配備Dell筆記本作爲工作電腦

②C老師最近剛加入X團隊

通過這兩點,我們可以推導出,C老師很可能也使用Dell筆記本。

但你要清楚歸納的結論並不必然爲真,如果遇到邏輯推理出的必然反例,即使再不符合常理,歸納的結論也會被推翻。

比如除了上述兩點,我們還知道:

③C老師簽約了蘋果公司代言

④蘋果公司的代言人不得使用其他品牌的手機和筆記本

那麼,上述“C老師使用Dell筆記本”的結論便不成立。

雖然歸納不是必然,但在解決問題時依然重要。尤其在開發中遇到錯誤需要 debug(調試)的時候,並不是所有錯誤都可以直接從報錯信息看出問題(比如 Python 開發時經常出現的亂碼問題),這時如果有豐富的經驗和較強的歸納能力,效率會大大提升。這也是資深程序員和初級程序員之間差距的重要體現。

現在網上的編程教程鋪天蓋地,不過呢,大家都喜歡寫寫怎麼編個爬蟲抓圖片、抓數據之類,卻很少有文章願意講講背後的思維過程。寫了讀者也不願意看,因爲看不出什麼效果,哪有調幾個函數就出結果來得爽快。以至於你發現,照着例子也能寫個一樣的代碼出來,但是一旦報錯或者沒有預期的結果,就完全抓瞎了,只能把參數東改改西改改,反覆運行,期待某一次奇蹟出現。以後換個新的問題,依然不知道從何下手。

這就是因爲並未理解程序背後的邏輯。我常在答疑羣裏說:遇到程序出錯了不要去猜!要去做假設,再通過輸出驗證假設,最終定位問題所在

文本只是一個引子,不可能讓你對邏輯融會貫通。但前面講的那些邏輯基礎,任何一本《離散數學》或者《邏輯學》的書上都有,而且僅僅是最開始的一小部分就很受用了。找一本來看一看。真想好好學編程,不要只侷限於讀網上的教程,這些都是別人嚼爛喂到你嘴裏的。如果你只能接受這樣二次加工過的知識,而沒有自己咀嚼的過程,那麼你學習上的乳牙永遠都掉不了。


瞭解邏輯學和思維具有邏輯性並不完全等價。有人沒學過邏輯,說話做事一樣很有邏輯性,而有的人雖然學過邏輯,也不過是當做數學公式在背,整天“邏輯思維”掛嘴邊不代表做事就講邏輯。

在網絡上,你經常可以看到一些邏輯謬誤,舉幾個常見的例子:

  • 以偏概全:你說用X產品遇到了Y問題。有人就反駁說,我也用X產品,我身邊人也用X產品,都沒有問題,所以你一定是故意黑。
  • 關聯當因果:某地區的人喜歡喝生牛乳,同時該地區人平均壽命高於周邊地區,所以喝生牛乳可以延年益壽。
  • 非黑即白:網上都在抨擊某個產品竊聽用戶聊天,並且之前也有發垃圾廣告的前科。你說竊聽從技術上來說不現實,目前也缺少明確證據。然後就有人認爲你不一起噴,你就是水軍、洗地、舔狗。
  • ……

類似的不講邏輯充斥着網絡。這兩天,網上很多人說“不買華爲就是不愛國”,對此任正非專門迴應說:不要煽動民族情緒,不能把買華爲與愛國簡單等同起來。其實無需任總髮話,這句話本身從邏輯上來說就是錯誤的。

不買華爲→不愛國,這個命題在邏輯上應等價於它的逆否命題愛國→買華爲,也就是說愛國的人就一定會買華爲。你這讓拿着小米、OPPO、VIVO的愛國同胞們情何以堪。顯然,愛不愛國並不由網友定義,只要存在一個愛國但未購買華爲的人,這句話在邏輯上就不成立。

我們的周圍有很多偏見、歧視的觀念,還有很多喜歡爭論的“槓精”,歸根結底,你會發現這些人都有一個共同的特徵:邏輯混亂。比如,之所有有人會有性別歧視、地域歧視,就是因爲以偏概全地由一些特例而對整體作出推論。而反過來,有些人沒有被公司錄用,就歸因是自己的性別或籍貫遭到了歧視,就又是另一種錯誤的邏輯。而偷換概念、顛倒因果、動機揣測,更是槓精們喜歡濫用的邏輯謬誤。

爲什麼總有些人談論觀點時不講邏輯?假定一個人要麼懂邏輯,要麼不懂邏輯。懂邏輯但不講邏輯,說明他帶有某種目的而刻意爲之;而不懂邏輯,卻還要跟人強詞奪理,說明他欠缺認知能力且不自知。所以說,不講邏輯還硬扛的人,不是__,就是__。(歡迎對號入座)

不僅僅是在編程上,如果我們更講究邏輯,這個世界的矛盾就會少很多。即使沒經過專門的學習和訓練,只要保持謙遜,學會傾聽,以包容的心態對待不同的聲音,多去思考一下對方的觀點,從不同的角度看問題,你的邏輯就會更完備。

否則,當你發現網絡上全是不講邏輯的言論時,就不想再發表任何觀點了。

----

PS:留個作業:

這是『知乎』和『王者榮耀』的百度指數,王者榮耀高的時候,知乎就低,所以是不是說:如果人們不打王者榮耀,就會都來上知乎呢?[手動狗頭]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章