藏經閣

一切有為法,如夢幻泡影,如露亦如電,應作如是觀。

來源:豬言豬語

數 學對於程式設計師來說到底重不重要?!類似這樣標題的討論,在網路上已經不知道被討論多少次了。前兩天又在老同事小白的blog上看到了他的看法。以前正 方總是喜歡拿演算法與效率來表明數學很重要的立場,反方或是最近普遍的觀點是要依照需求。兩方都沒錯,我也有一點小心得跟大家分享。
先來談談「數學」在大家的心中是長什麼樣子。我大學時念的是輔大應數,會選應數的原因是一、我的分數上不了資工,二、應數又跟純數不一樣,是比較偏電腦應 用的(事實上不是這麼回事),應數的全名是應用數學。三、高中時一位要好且電腦很強的同學也是唸輔大應數,所以我就這樣進了數學系。在一般人眼中是個很硬 的科系,那幾年全校1/2的名單中,數學系就佔了一半。數學系所學的數學,跟一般人所會用到的數學不太一樣。除了幾門工科必備的微積分、線性代數、機率統 計外,剩下的都是高深且抽象的數學理論,像是高等微積分、高等代數、幾何學(不是三角形、正方形那種簡單幾何)、拓撲學等。這幾門課程跟本像天書一樣,非 常的抽象(無法畫在直角座標系上),我能畢業也算是一種奇蹟啊~~我真懷疑我那學唸到博士班的同學們,他們的腦袋是不是跟我長得不一樣。

研究所順利考上的嚮往已久的資工所,成為名符其實的本科系學生,本以為可以不用再玩數學了,但我發現我錯了,是不用再玩那些抽久的高等數學沒錯,但線性代 數、機率統計、離散數學等…用了更多的數學,我想不出來有哪門資工研究所的課沒用到數學的。而且你最後的碩士論文要寫出來,數學更是不能少的。你以為玩網 路不需要數學?大錯特錯,裡面一堆機率統計的東西。電機需要數學嗎?當然需要!最基本的傅利葉轉換就夠搞死你了,所有工科的系所都逃不了數學的魔掌。就算 你到了管理學院,會計系要數學、經濟系要數學、連心理系有些領域也需要數學。雖然所需要的數學不盡相同,但都在數學的領域裡。我開始後悔當年沒把數學唸 好,博士班念到一半唸不下去了,其中一個原因是我數學太爛了。

寫程式需要數學嗎?要看程式的目的?那我們就像討論一個簡單的程式,算出1加到100的總和。

完全以程式結果為導向的人,或是訓練有素的程式女/男工,甚至有時連我都會很直覺的寫出這樣的程式:

int sum = 0;
for (int i=1; i<=100; i++) sum += i;

上面這個程式片段還算很容易讓人一眼就看懂,可是我們明明國中時就學過了這種數列級數的算法了,怎麼還會寫出上面這麼笨的程式呢?

int sum = ((1 + 100) * (100 - 1 + 1)) / 2;

或更精簡的

int sum = (101 * 100) >> 1;

這個例子已經被說爛了,我們來來看另一個例子,計算1加到10000,奇數和偶數的總和。用迴圈的話,一樣很直覺得就寫出來了:

int oddSum = 0;
int evenSum = 0;
for (int i=1; i<=10000; i++)
{
if (i % 2 == 0) evenSum += i;
else oddSum += i;
}

很簡單的程式吧!可是我們稍稍的用我們有12年(國小到高中)的數學背景想一下,你可以寫出更精簡的程式:

int sum = (10001 * 10000) >> 1;
int evenSum = 5001 * 5000;
int oddSum = sum - evenSum;

什麼?看不懂?!sum應該知道怎麼算出來吧?就剛剛第一個例子是1加到100,現在改加到10000而已。evenSum呢?簡單的推理一下,1到 10000之間的偶數總和是2+4+6+...+10000,把它們全部除以2的話會變成1+2+3+...+5000,所以1到10000偶數的總和 不就是1加到5000的兩倍嗎?

1加到5000是:
(5001 * 5000) >> 2 兩倍就不用除那個2了,所以不就是上面那個算式了嗎!

那1到10000奇數的總和不就是全部的總和減掉偶數的總合嗎!稍微動一下腦袋,可以讓你的程式變得很有效率。怕別人看不懂?是不會加個註解在程式碼裡面喔!

相信聰明的你,很容易就可以分析出來這兩個例子的兩種寫法,在效能上迶多大的差異,但這不是我在這裡想要表答數學是如何如何增加效率的。我想要表答的是, 我們明明辛苦了12年,學了一堆的數學,為什麼我們要放棄這樣的基本訓練?我們笑美國人的數學不好,請問你又用了多少的數學來幫助你的生活和你的工作?學 了又不用,那不如從小學開始就分科系好了,不喜歡數學、怕數學的,就選完全用不到數學的科系。

我今天不是要大家在寫程式是時鑽研那種演算法、功式等,去計較那些在現在動不動在2GHZ, 3GHZ,雙核心、四核心之下,所省下的那微小的效率。而是你的態度!你寧願多打一些code,也不願動一下腦筋,如果你的態度是這樣子的話,那也是活得 下去啦,不過你的水平就不過如此而已。

你會反駁說,需要用到演算法、要講求效率時,我再去研究一下就好了,幹嘛說的很嚴重似的。今天我們一時興起,要去爬陽明山,沒問題啊,那種程度的山,只要 雙腳健全走得動的人都能爬。如果換成現在流行的登山步道呢?這需要一點點體力才行。如果你要去爬台灣百岳呢?合歡山的東峰算是最簡單的吧?開車到山腳下, 穿個好一點的鞋子、好一點的衣服、多一點的體力,也還不是太大的問題。那爬玉山呢?雖然現在爬玉山已經很方便了,連行李都可以請人幫你背,但平常沒有一些 訓練,要爬上去不是那麼容易的事。你要站在世界的最高點,去挑戰聖母峰,那全世界沒幾個人辦得到,而且辦到的人事前可是經過了嚴格的訓練。

你想把自己擺在什麼位置?你想要成就到什麼樣的高度?如果你只想在小小的台灣,在二、三流的公司裡,打打專案游擊戰,賺個還算可以的薪水,那的確,你不怎 麼需要數學,連軟體工程的理論也不太需要,最重要的唬弄客戶的技術純熟就可以了。去年去了101的37樓面試後,我才知道我了不起只爬到阿里山而已,要登 上MountainView這座山,我必需十倍努力才行。而這個努力不是我在面試前,看看什麼教戰手冊、寫寫網路上的考古題我就能夠通過的,而是必需把一 些數學的訓練熟到變成很自然的反應才行。簡單的問你就好了啦,上面那個用迴圈寫的1加到10000的那個例子,如果10000改用n的話,那需要多少時 間,用大O(big O)來表示。如果你不能很快的推論出是O(n)的話,那你的履歷連投都不要投,在37樓問的問題比這難多了,而且你沒幾分鐘的時間可以作答。去年那次,是 我第二次後悔當初沒把數學學好。

為什麼Google會這麼重視演算法和效率?應該說世界級的大公司都重視,Yahoo、微軟、YouTube…,因為你寫的程式不是給幾十個人、幾百個人 用而已。而是同一時間有幾百萬,甚至上千萬人使用。一個人慢0.1秒好了,一百萬人就10萬秒,超過一天耶。瀏覽一個網頁,慢個幾秒鐘你都不能忍受了,更 何況是一天。你說能不計較演算法和效率嗎?!

你想過什麼樣的生活是你自己決定的,但你想要當個世界級的軟體工程師的話,把學數學就當作是一種修行吧!不要怕沒地方用,因為你時時刻刻都可以用到它。當你的修行到了某個程度,要挑戰高山,就比別人容易多了。

好好好,不想深入就算了,但你不覺得放棄12年的數學訓練很可惜嗎?至少花點腦筋用一下嘛~~,大家都多少用一點,台灣軟體的水平就會慢慢提升了,你說是嗎?

感覺起來大家還是對於我在上一篇文章中的論點不是那麼的了解,我想要表達的是我並沒有要求堅深、精美的數學演算法, 而是要大家在平常寫程式時,多想一分鐘,把你所約到的數學用上來,不需要多資深的數學背景,只要我們在大學以前所學的12年數學就夠了。目的是什麼呢?為 了有一天需要用到更深一層的數學來解決問題時,做好平日的練習和準備。呃...還是無法體會?我再舉個例子吧。

小明跟小華平常在班上的成績都不錯,但小華不愛小功課,常常到了要交功課的前一天,才向小明借來抄。小明基於朋友的立場,常告戒小華說,老師出功課的目的就 是讓我們平常就把學到的東西熟練,這樣到了考試時才會準備的比較輕鬆。小華腦袋不錯,有點小聰明,但就是愛玩,他覺得浪費時間寫那些功課不如拿去控電動, 功課有交出去就好了,老師也不知道是抄來的,考試?!考前三天再熬夜準備就好了。平常的小考、月考小華還應付的不錯,因為小華頭腦其實不差,所以臨時抱佛 腳的效果還不錯。但終於要到關鍵的基測大考了,小華花了一兩個禮拜來熬夜準備,但考試結果沒有比輕鬆準備的小明來的好。

實力是慢慢累積而來的,也許你很聰明,可以在短時間內硬塞進一些東西在腦子裡,但經驗告訴我們,臨時抱佛腳所讀到的書,在交卷後一秒鐘就全忘光 了。就像農夫為什麼平常要努力的耕田、翻土一樣,要播種時再耕就好了,幹嘛平常就要再那辛苦的挖來挖去呢?大家應到都知道這老掉牙的道理,沒有平常辛勤的 耕耘,怎麼會有豐收的成果。臨時翻土,種得活是運氣好,收成的爛是理所當然。

還是有人在「程式目的」這點上做文章,經過我再次的解釋,不知道大家了解了沒?煎荷包蛋不難吧?同樣是煎蛋,有沒有練習還是差很多的。不知道各位 爸爸們,換尿布的工作是不是你們負責?換尿布也沒什麼難的,但你平常沒熟練,臨時要你參加換尿布比賽,你也是會手忙腳亂的。程式目的不是我的重點,我要寫 的程式也不是專要來解決某個數學問題用的,程式裡本來就到處都有數學的影子。平常多練習一點,有一天需要用到大量的數學時,你就能很輕鬆的應付,而不是眼 睜睜地把機會交到熟練數學的人手上。

文言文?白話文?程式可讀性?信不信就是有人連簡單的迴圈也可以寫得亂七糟,也有寫得很複雜的迴圈,讓人很難了解在幹嘛。程式註解才是程式可讀性 的關鍵,我們不是天天都在一行一行的trace別人的code,事實上我們平常也很少看別人的code,除非你是要改作業、最佳化調整、找別人的Bug之 外。不靠註解,要看懂別人的程式真得很累。就像基測的作文,平平都是白話文,但是有人寫出來的文章就是讓人看不種一樣。

下面這個迴圈在做什麼呢?
int a = 1;
int b = 0;
int c = 0;
for(int i=1, j=-2; a<12346; i+=2, j+=2, a+=2, b+=i, c+=j);


如何在Blogger新增隨機文章

Blogger Hack - How to add a Random Post Gadget in Blogger)

 


5 意見

  1. 阿咩  

    很確定的是 數學與程式設計
    是有相關的關係
    但是並不是絕對的關係

    尤其在在寫圖形程式
    更試用到一堆三角函數

    所以說...

    要開發高效能的程式或是高難度的
    數學可能還是要學醫學

  2. Tommy  

    To 阿咩,
    的確,當初在學計算機圖學時,為了效率
    連劃一條直線,當可以講很多數學
    更別說線上遊戲那些複雜的圖形

  3. Lee  

    完了
    我是個私立大學生
    但數學真的爛到爆炸,沒及格過
    那我該如何補救???
    數學可以自學嗎? 從國 高中的數學學起

    很焦慮....
    也很後悔數學沒學好...

  4. csie-tw  

    To Lee,
    從自己有興趣的著手吧

  5. Jack隱者小幽  

    請問文章最末的迴圈,是不是在做:
    計算從1至12346之中奇數與偶數的和?

張貼留言