寫程式到底需不需要懂數學?」在程式開發界是個萬年老哏的題目,基於開發者座落領域的不同,每每這題目一出現,各路人馬就會展開一場廝殺。實際上,這題目對「懂數學」的定義太籠統,畢竟不同領域應用到的數學也各不相同,若不知道對數學的瞭解該拿捏到什麼程度,那麼從Maker的世界中尋找,或許就能有具體的分寸。
問題只靠程式邏輯解決?
討論「寫程式到底需不需要懂數學?」這個題目,已經老哏到無趣了,不如改來討論另一個題目:「所有問題只靠程式邏輯解決是否可行?」就算出1加到100總和,這個常用來說明數學對寫程式重要性的範例來說,我也可以反過來說,就算不懂等差級數,使用迴圈也可以解決這個問題(通常還可再附上一句:反正老闆又不關心怎麼寫),這麼說來,所有問題都能只靠程式邏輯解決囉?
想想n從1到無限大的等比級數1/(3^(2n-1))總和,單純用迴圈的程式邏輯來跑,會是無窮迴圈,結果也不見得完全正確。
以Java來說,受限於浮點數精度,結果會一直停在0.3749999999999999,而不是0.375。就算不是無窮級數好了,假設有個函式(10^n)%3,想知道n從1到1000的結果各是為何,表面看來,在程式中可以用迴圈跑出10的n次方再去做餘除;然而如果是Java,必須處理整數溢位問題;Python中,雖可以自動以長整數處理,效率卻不好(O(n^2)),如果知道對於模數3來說,10^n與1同餘,就可以直接跑出長度為1000而值皆為1的結果。
這也就是一些支持寫程式要懂數學的開發者,所提出的論點。有些問題如果純粹使用程式邏輯來解,會非常沒有效率,像是1加到100總和這種問題;有些問題則會受到硬體限制,像是整數溢位問題,因而在程式中處理會額外花費些功夫,例如在Java中,必須使用BigDecimal來解決(10^n)%3這類問題,程式撰寫相對麻煩。
在面對這些問題時,若能以數學思路解決,就能產生各種有效率且方便的演算法,因而支持要懂數學的開發者,經常將結論導向對演算法和效率的重要性。
不過,對某些開發者面對的領域來說,比較不容易遇到純數學的問題,而有些問題直接以程式邏輯來解決,效率上也不至於難看到哪裡去,又因為現在大部份重要的資料結構或演算法,都已有現成程式庫可以使用了,使得實際投入研發演算法的機會少之又少,這就是為何,不少主張數學對寫程式不那麼重要的開發者,會持有「程式生得出來就好」的論點。
多一種解決問題的方式
如果就「程式生得出來就好」這個論點來說,我想物件導向、函數式等典範,以及為了令軟體易於抽象、重用的各種設計原則,就都不必要討論了,一切都用複製、貼上、改幾個變數就好了,至於程式碼到處重複而產生不易維護的問題?那就掃描程式碼進行搜尋、取代就好了,如果會Regex的話,那就更方便了不是嗎?
擅長程式邏輯的開發者,擅於使用程式邏輯來描述問題以及解題的過程,而擅長數學的數學家,則擅於使用數學推導來描述問題以及解題的過程,兩者都是描述問題與解題方式,而有些問題實際上可以是程式邏輯與數學推導都能解決,如果開發者正好遇上這類問題,而又懂其在數學上的思路,那就會多一種解題方式的選擇!
這有點像是關於領域知識重要性的討論,如果你擁有某些領域知識,那麼,在某些適當的地方,套用領域知識,會比直接使用程式邏輯蠻幹,來得有效率。
就像我先前專欄〈從40個判斷式到1個算式〉中,提到了決定音階頻率的問題,如果能略為套用音樂領域的基本知識,就能使得程式更易於撰寫且有彈性。然而,反過來說,如果事先不知道這個基本知識,我就無法知道這個問題也可以用算式的方法來解決。
類似地,開發者對於某些問題若沒有數學上的敏感度,往往就不易察知問題還能用數學來解決,因而第一時間就傾向於使用程式邏輯處理,所以,有些開發者會主張,平時就要涉獵一些數學來培養這類敏感度,以便在面對問題時能選擇程式邏輯或數學方式解決。
從這點來看,如果主張寫程式,卻完全不用懂數學,那就等於是選擇了「我遇到問題完全不想用數學來解決」!
數學要學到什麼程度?
只不過「懂數學」這問題真的太籠統了,要學到什麼程度,才說是懂數學?
如果一味鑽研數學,恐又直接迷失在一堆數學理論中,不是嗎?
確實沒錯,直接研究數學確實容易失去方向,有人會建議從電腦圖學、影像壓縮、語音辦識等下手,只不過有人覺得太枯燥,目標不具體,也不見得有興趣,如果你是這種人,可以試著朝Maker的方向探循,無論是自造什麼樣的東西,通常,就會開始遇到許多需要數學才能處理的問題,然後,就會知道具體需要哪些數學。
舉例來說,我最近利用空閒,自得其樂地設計一個可以用來繪圖的機械手臂,要能控制馬達轉速,這需要一點數學推導,我必須控制手臂角度,這就要用到三角函式計算,設計的過程中,大多數時間都花在數學計算上,只要數學公式推導出來,寫程式倒是很快!
如我先前專欄〈從Coder到Maker〉中講過的,Maker這名詞的新意義是「代表著一群能運用數位科技軟硬體,將自己的想法實現」,開發者有著程式設計的能力,在這時代可以自然地就投入Maker領域,而當進入這領域時,很自然地就得接觸一些數學,不單是機械領域需要數學,玩弄Arduino、Raspberry Pi等時,雖然一開始可以使用現成的電路模組,但是,真正要設計某些電子電路時,也需要數學!
最近摸著Maker界邊緣的我,發現自己三不五時都在算數學,當你開始自造一些東西時,自然而然地就能知道數學該學什麼,又該學到什麼程度,實際上,我之前試著做一個類似倒單擺的平衡機器人,發現到裡頭需要的數學,我大半遺忘了,這也不是單靠程式蠻幹就能解決的問題之一,因而平衡機器人的設計被我暫時擱下了,而去複習一些必要的數學了。
對程式領域的回饋
或許有人會說:「為什麼要當個Maker?這跟我的程式開發工作無關啊!」Maker這名詞實際上有著業餘玩家的味道,你選擇自造的東西不必跟原有的工作相關,只要與興趣有關、過程開心就可以了,而在自造的過程中,會自然而然地學習、運用到一些數學,學習這些數學的目的很明確,就是要解決實際出現的問題。
因為有了具體要解決的目標,就不會有為何要學數學這樣的問題,也更不用去思考數學與程式設計這條路上,想將自己擺在哪個領域、位子,取得什麼樣的高度或成就之間,有什麼關係,因為是業餘的興趣,原本的工作上用不用得到數學,也就無關緊要。
當然,如果真要就討論對程式開發上的回饋,那麼就是在自造的過程中,培養起來的數學敏感度,會使得自己在回到程式中面對運算相關問題時,自然地思考這類問題,有無以數學途徑解決的可能性,這時,就不單只是個技術純熟、有著良好程式邏輯,同時,也有個有能力選擇是否運用數學的開發者!
沒有留言:
張貼留言