身為一個基礎學科的研究生,你是如何提高自己的編程能力的?
從問題評論中,看到主要問題是查bug,那應該叫做改善編程習慣。
個人習慣是:
1. 先把演算法大致步驟寫出來,然後再寫程序,而不是一氣呵成。
2. 寫程序的時候要注意使用子程序(或者叫函數),這樣對相同功能的調用就會很方便。
3. 不要忘了加註釋,邊界條件要注意,除數為零情況要考慮。這裡的邊界條件,指的不僅是物理上的邊界條件,還有數學上的比如說數組長度之類的。
4. 如果算錯了,那麼用簡單的例子來做小白鼠,一行行執行,觀測其結果變化,定出最初算錯的位置,然後一步步推進;如果是程序無法編譯通過,再看看前三點我說的什麼。5. 如果遇到問題,自己暫時無法解決掉,那麼將問題梳理清楚,去問或者去討論。如果有一個計算機或軟體相關專業的好友,最好是高中參加過競賽的同學,他們在這個時候會提供很大幫助。
順便說一下,在沒裝中文輸入法的Fedora17的Firefox中,進知乎的回答欄怎麼無法用搜狗雲輸入法輸入漢字(輸入的時候,一直是字母)……我進百度的搜索行,然後一點點挪過來的……
6. 一個小建議,持續輸出某個可以代表當前進度的值,這樣至少可以把死循環避免掉;如果在這個輸出值中程序中斷了,,而子函數等都確定沒有問題,那麼要注意第3點——是否出界、是否除零。編程能力一般可以從兩方面來體現,一方面是運用框架的能力,比如在java中調用jdk解決問題,在windows中調用windows api來構件界面等等,另一方面則是運用數據結構和演算法的能力。樓主既然問到基礎學科,那麼我想演算法方面應該比較重要一些,那我就先談談演算法和語言基礎
工欲善其事,必先利其器,學習編程之前,應當先紮實地掌握一門語言,對於基礎學科的研究人員來說,C語言應當是最恰當的一個了,C語言語法清晰明了,效率較高,比較適合科學計算。
C程序設計語言 (豆瓣),C專家編程 (豆瓣)書對於掌握C語言的基礎偶有很大的裨益,在這裡要說的是,不僅僅要看懂書上定理性的解釋,還應當認真完成書後的習題,這些習題對了解C語言的一些特性都有很大的幫助。昨晚習題之後運用C的能力必當大增
接下來就要開始看看數據結構和演算法了,這裡我要推薦這本書 數據結構與演算法分析 (豆瓣),這本書對於數據結構的入門是有很大的幫助的,接下來,可以讀一讀演算法導論 (豆瓣)這種大部頭的書,或者讀一讀演算法 (豆瓣)這種小部頭的書。
然後就是讀一些開源項目了,C標準庫,STL,linux/unix的源碼都是很值得一讀的,樓主可以看一看unix系統中怎樣用宏來實現一個鏈表或一個隊列,並自己試著實現一下,這些都是很值得做的。
最後,建議樓主時常去TopCoder, Inc.,Programming problems and Competitions :: HackerRank等網站去刷一刷題,編程時很有趣的,祝樓主成功我是一個數學很差卻仍在做物理的人。
我在國內化學和材料類專業感受到的最主要的問題就是學生普遍數理基礎都很差。雖然也要學數學和物理,但都屬於白學了的那種。本科畢業的腦中的物理圖象仍然一塌糊塗,也不願意主動進行抽象和空間思維,演繹能力差。事實上,只有重點大學物理系裡的一些腦子靈的小夥子具備繼續討論的前提,但對於這些人編程什麼的也根本不成問題了。可以說對於這類人讓它自學任何東西然後現學現賣都不成問題。
在化學和材料專業的學生中,總有很多人是最起碼的變數概念都沒有、不理解y=y+x的完完全全的編程盲。或者說,電腦對他們來說就是一些user friendly的軟體界面。他們要從每三五行就一個bug的水平到寫出幾百行的代碼做個有限元,要走的路太長了。不需要到演算法的層面,一些最基本的編程的小技巧,都是要平時長期玩長期網上找答案而積累下來的。如果思想上不是有著一種解決問題的主動心態,而是很困惑很抗拒只想早點解脫(例如一些女生),那就可能永遠也不會進步到能解決問題的編程水平。至少數組、函數那幾塊就可能停很長時間。連書上或者help里的範例代碼都讀不懂的水平。而且debug也是需要經驗和技巧的。不怕bug的人與其說是因為寫的時候出錯少,不如說是因為他debug的經驗和能力很豐富。一個看一晚上都看不出來的bug可以永久地澆滅一個人對編程的興趣。
好,如果你說,你以前也對編程感過興趣,學過一下VB之類的,那就很好。但這時應該做的不是直接去編程,而是補習數學,搞清楚一些科學研究方法的概念性問題。例如很可能同樣給個方程,他會分不清去「擬合」和去「預測」有什麼區別。或者方程直接就看不懂,沒學過張量,雙點乘以為是冒號直接輸到電腦里,等等。先不要管怎麼編程去運算,寫在紙上的數學式子要都能看懂了。這種能力對於國內學生是不保證的,要花相當的時間去看教科書。除了說僅僅把公式看懂需要數學之外,有很多方程的具體形式造成了它解的時候難收斂,你要先對它進行一些「改造」,這種sense則需要更高的數學敏感度。有的人說,也可以優化演算法。但是對於「學過一下VB和微積分」的本科生,微積分一定學得比VB好,讓他們在解析的世界多做事比在數值的世界多做事要來得容易些。但仍然有很多人僅僅化簡幾步就不得不抱著數學用表翻來翻去。
接下來就是仍然逃不開去看《數值方法》(numerical method)教科書,這是核心。否則,你哪怕直接使用Matlab的ode45,也完全靈活不起來,因為你不明白為什麼ode45需要這麼些個信息來解你那個方程,那個你手工解完全沒戲的微分方程,電腦是如何能夠算出結果來的?這樣的知識不具備的話可能就只能用比ode45更傻瓜的軟體了。而且,有很多任務還是需要自己重頭寫的。
有的人說MATLAB慢。對的,不過,對於做材料類研究的課題組,用經費買台性能優異的計算機比起讓學生改學C++來得更容易些。
可是,進行對實驗結果進行一些數值分析,從世界範圍來講,是理工科研究的必備能力,無非是中國的理工科教序(物理類的除外)這方面教育缺失而已。如果無非是投一篇稿子的時候審稿人叫你拿哪個模型預測比較一下,你就要完成上述的整個歷程,那乾脆改投別的雜誌拉倒了。我覺得對於一個課題主要是過柱子打核磁的國內研究生,很難要求他去做這件事。但是在國外卻不一樣。至少我去過的KIT高分子化學樓里的學生,似乎都不害怕要去碰MATLAB,或許因為他們本來就有很多師兄師姐懂這個了,本來就有一種輕易用一下MATLAB氣氛。如果你看到一博士論文的前四章全是做合成於是認為他一定數學很差那就錯了,很可能會被最後一章亮瞎。
作為experimental physicist,除了編程解決數學問題之外,更經常遇到的是編程解決真實世界問題,例如給51晶元編程來控制一個馬達的伺服這種基本DIY技能。一些基本的單片機編程技術在儀器房裡是很吃香的。可是,在國內你是很難想像這種能力是化類學生的標配,只能說是可遇不可求。你叫學生從連什麼叫「中斷」都搞不清楚,焊十個點八個虛焊的水平,到做出一個帶反饋的測量控制部件,你準備給他多長時間呢?大多數學生只想做現成能做的事情來畢業,要看這麼多書才解決一個小問題,他們往往乾脆選擇繞開。讀研對他們來說只是一項投資,拿學位找工作是他們要的結果,代價就是要花三五年時間。叫他們在這三五年時間多花一分精力,都是讓他們拿到的學位的性價比減小一分。
所為什麼華人做納米自組裝材料這方面的論文最厲害?因為這些研究是過個柱,打個核磁,照個電鏡,掃個AFM,拍個數碼照就能發JACS或者Adv Mater的,非常適合中國研究生的平均生源質量狀況,也非常適合中科院包工頭式的「生產模式」,學生只需要幹活就行。
從題主女友的情況看,好像她想問這個問題的原因無非是把編程當成英語,看到別人很牛,覺得自己「提高一下總是好的」?但哪怕是這樣,我也想說英語好的人是因為他自己感興趣、平時對英語現象非常敏感而長期積累回來的。編程也差不多。其實,陳浩好像是做數學的,傅渥成好像是不沾實驗的。人的時間是有限的,一天只有24小時。努力程度相當,也要找一個背景相似的人來看齊,而且這也是可遇不可求。我一直就苦於找不到什麼這樣的標杆。都比我牛好多,或者都比我系統。
最後還是給些直接的答案吧。我的應用現狀:MATLAB可以做絕大部分的數值分析工作。Mathematica我只習慣用來作為一種符號運算和認識陌生函數行為的東西,用得不多。對於一些普通方法很難做的擬合,我也會找一些現成的工具包。簡單的蒙特卡羅用MATLAB都可以做一下。如果專門要做計算機模擬,就用Materials Studio。但是,世界上很多人不用Windows系統。世界上也很多人沒錢。所以就出現了很多Sage、R、Octave等東西。我的觀點和其他答案不同……
當然,如果你能掌握演算法和數據結構,在科研中幫助是相當大的。如果有時間有精力,請參考其他答案。但現實是,許多從事基礎研究的,在系統掌握程序設計的基礎之前,就迫切需要在科研中應用,解決實際問題。因為本科課程設置不合理,這個問題在國內尤其嚴重,但國外也好不到哪裡去。
好消息是,用程序解決科研中的實際問題,不一定要像計算機系那樣掌握演算法,數據結構,不一定要會 C++ 等「高級」語言。
- 迫切需要學習的課程,不是「演算法與數據結構」,而是計算物理。要掌握的技能和知識是數值分析,求特徵值,解常/偏微分方程,分子動力學模擬,蒙特卡羅模擬,等等。
- 盡量不要自己編程,善於利用現成的工具。除了常見的 Matlab 和 Mathematica 之外,各學科有自己的軟體。比如表面物理中的 Surface Evolver,圖像處理用 ImageJ,純數學用 Sage,Macaulay2 等。分子動力學模擬也應該有專門工具,我不了解。
- 迫切需要掌握的程序語言,以 python 和 java 優先。python 的特點是易理解,語法學起來非常快。許多專業程序直接借用 python 的語法。java 的特點是資源豐富,很多東西現成有了。學會這兩個,就可以利用大多數已經做好的數值計算工具。
- 軟體工程,面向對象編程這些,都是不必要的。科學計算不是商業軟體,也很少有分工協作。程序大多非常非常短,在計算機專業看來可能很亂很臟,但能解決問題就行。因此只需要面向過程的思維就可以了,面向對象的作法反而會把事情搞糟。
- 學有餘力的基礎上,向計算機系的要求靠攏。否則,仍然以解決當前的問題為第一動力。
- 加一條,關於 Fortran。如果對程序的性能要求很高,或者要在超級計算機上跑,那麼 Fortran 絕對是不二之選。如果只是一般計算,用 Fortran 我覺得有點浪費。如果決定用 Fortran,那就該對演算法有點研究,也要對複雜度有感覺,否則太浪費神器了。
最後提一下:
我發現國外許多常用專業軟體/程序,國內的知曉率非常低。但想想也知道,如果每次碰到問題都需要重新編程,那麼科研效率怎麼可能提高?
事實上許多問題都能在網上找到現成工具,只是這些工具可能非常小眾,有時得去作者的個人主頁上找。由於不是商業軟體,這些工具也經常對用戶不太友好。但是他們真的可以大大節省精力。原應數科班生來回答一下這個問題。要在科研實踐中有效使用編程解決問題,需要點以下技能點。
編程篇:
1. 熟練掌握一門高性能計算語言,比如C或者Fortran,以及配套的高性能計算軟體庫
- 學習C和Fortran的過程中也要了解它的編譯原理,知道什麼時候分配內存,什麼時候做計算,什麼時候需要做memory footprint優化。同樣的演算法,每個人寫出來的效率可以天差地別。把一個數值演算法寫對到寫快,有很長的路要走。
- 學習相關的矩陣計算和代數工具,比如做dense矩陣的BLAS,LAPACK,比如做sparse矩陣的PETSc,SLEPc,Eigen等。
- 學習基礎的優化工具,比如LP,QP的商用solvers
2. 熟練掌握一門數值計算工具,比如R或者Matlab,熟能生巧。
3. 學習至少一門符號計算工具,比如Mathematica或者Maple
(註:一般在科研過程中,以上三種語言的使用順序是倒過來的!)
4. 了解一些軟體工程初步以及編程規範,可以大大提升自己的工作效率:比如如何管理代碼,如何規劃代碼結構,如何設計框架和實驗的pipeline等。
5. 掌握一種基本的數據可視化工具,比如gnuplot,Matlab等理論篇:
1. 數值線性代數:矩陣怎麼分解,怎麼算特徵向量?
2. 數值分析:怎麼做數值積分微分,怎麼算梯度散度旋度?
3. 數值優化基礎:怎麼做擬牛頓迭代,怎麼做稀疏優化?
(註:以上這些都可以看書)
4. (可選)演算法基礎:實際上,在科學計算中,離散演算法用到的相對不多。實踐篇:
當然最重要的是結合手頭的項目,把學到的編程能力和理論知識在實踐中得到鍛煉。編程方面可以考慮,怎麼優化代碼,怎麼驗證代碼的正確性,怎麼重構實驗框架;理論方面可以考慮怎麼做更有效並快速的近似,怎麼重新設計演算法。隨著你實踐的深入,你自然就有了很多經驗,比如在用matlab的時候你就不會疑惑什麼時候用eig什麼時候用eigs,寫C的時候知道什麼時候調用BLAS什麼時候可以自己寫,設計優化的時候知道什麼時候應該用線性規劃而不是自己想一個組合演算法。
換句話說,我列下的這些都是普通CS科班不大能學不到的東西,而這些東西對科學計算的意義卻也是十分重大的。其實我編程能力最大的提升在三個地方,一個是SICP自學的時候,另外是看侯捷的 STL源碼剖析 的時候,最後是看 Loki庫的八卦 Modern C++ 的時候
所以為什麼不學點範疇論和 Haskell 呢(逃
我來說一下我的吧。
我碩士是做分析化學的,天天就是和儀器打交道,博士轉到模擬方向,不過基本上前兩年還是在和化學打交道,最後一年才真正轉到模擬方面。我做的模型大部分還是需要自己寫代碼,現在基本脫離實驗一線,天天處於碼農狀態。
我自己基本沒正兒八經學過編程,高中時候會考考過VB,大學閑著沒事兒去選修了Java,但是基本都是處於非常非常初級的入門狀態。研二的時候老闆直播,轉方向做模型,於是就誠惶誠恐地開始真正學編程。一開始學的是Fortran,因為老闆之前自己用的是Fortran,學差不多後發現老闆用的是坑人的Fortran77,遂考慮換平台。後來轉用Matlab,買了本教材,連學待查,算是編出了一些東西,入了門,基本上我所有演算法的知識都是在Matlab平台上掌握的。在Matlab平台約莫寫了1w多行代碼,
後來到米國老闆聯合培養,這裡以C語言為主,並結合Python和Perl。所以花了兩個月啃了C的教程(坑爹的指針!),Python基本是邊查邊用,和這裡的人合作寫模型構建程序,也貢獻了數千行代碼。現在是Matlab,C,Python和VBA配合一些Batch腳本語言混用,自認為算是一個合格的Modeler。
我自己從分析化學一路過來,就我觀察,我身邊人提高編程能力的最大障礙就是害怕編程,恐懼編程。一旦遇到和編程有關的問題就非常恐慌,覺得自己一定做不好。其實寫一個簡單腳本解決一些小問題一點都不難,日常的數據擬合什麼的只要肯潛心看看網路上的教程,任何人都可以做得很好。我自己學習編程的經驗就是多學多看多寫,也沒有什麼捷徑。
如果是基礎學科的學生,基本還是利用程序來進行簡單的數據分析,結果提取或者數據擬合,我建議從Matlab和Python學起,簡單實用。另外如果數據多的話可以學學VBA,把自己從重複的勞動中解放出來。有精力的話也可以在這兩個平台上深入摸下去。如果完全掌握了一門語言的精髓,後面換語言大多也只是細節不同,學習成本會低很多。
韓兄的問題必須答一下
C語言的部分樓上已經答了,C++一直認為《C++ Primer Plus》是不二選擇,我帶學弟用的也是這本書。
下面就是數據結構,竊以為這是整個編程學習中最重要的部分,更甚於語言,Sedgewick的《Algorithms》對各類演算法的闡釋很是詳細和精到,推薦。
數據結構之後其實直接看CLRS已經沒有什麼突出的困難了,更重要的是這本書其實可以當演算法字典來用,但不建議不學數據結構直接上演算法導論,那樣會暈的。
既然是科學計算,並行計算便是其中很重要的環節,這方面我並不是太熟悉,直接傳送門 http://www.amazon.com
最後建議在C/C++之外再學一門多範式的編程語言,比如C#,或者Mathematica,這樣的語言一來能開拓眼界,二來寫原型比C快得多,想出來個演算法能很快的實現而不是把創意浪費在無窮無盡的Bug上面。
特彆強調Mathematica,無論用來做模擬還是數據可視化,都是非同一般的方便,含淚推薦編程就像寫文章。
「無它術,惟勤讀書而多為之,自工;世人患作文字少,又懶讀書,每一篇出,即求過人,如此少有至者。疵病不必待人指摘,多作自能見之。」——歐陽修
這跟你從事什麼專業並沒有關係。當然,對大部分科學計算應用來說,熟悉C和FORTRAN的代碼編寫就綽綽有餘。這是因為許多重要的計算方法都有現成的包可以用,比如DFT,比如QMC,需要你自己去實現的真不多。有時候需要調用一些數值演算法,也有GSL(GNU Scientific Library)或者LAPACK提供現成的函數和子程序。可見這個門檻其實是很低的,但也沒有什麼速成捷徑,關鍵是多讀多寫。
作為一個基礎科學研究者,你關注的點應該更多是領域內的概念和研究本身的一套邏輯,而不應該投入過多精力在編程這樣的技術活上。當然,如果你真的有志做一個計算專家(或者想轉行),那最好還是進一個靠譜的計算組,讓內行手把手教你。
你需要記住的是:學習任何一門語言的寫作,想要揚名立萬都需要天賦,但要做到諳熟技巧,則完全仰賴時間和練習的堆積。
鑒於樓主的問題主要在於C和Fortran遇到的基礎性bug不會解決,那麼推薦MATLAB、Mathematica、Python、Java等相對好寫的語言並不能解決問題,利用已有的Fortran和C代碼或許是必須的。
針對C和Fortran,建議學習一下基礎的計算機體系結構的知識,編譯器、調試器、內存優化器(Valgrind之類)的使用,然後就是刷一刷常見的C/C++語言編程評測系統的基礎題庫部分,做完這些題目應該就不會犯基礎的程序錯誤了。另外如果用C++,盡量使用非指針寫法。
個人認為現在這個階段看書沒什麼用,大量動手,進行調試,積累經驗非常重要,善用Google和Stackoverflow搜索錯誤信息。
學習和使用Linux或許也有助於提高一些方面的計算機素養和Debug能力和效率(終端比較好使),LLVM和GCC用起來也比較方便。我來說一點自己的經驗吧
個人認為,科研中的編程,以解決具體問題為導向,充分使用現有工具是比較好的方式。另外,
一定要有自學能力和內部驅動力
一定要有自學能力和內部驅動力
一定要有自學能力和內部驅動力
重要的事情我也說三遍。我的編程都是自學的,大學規定的課程之後就沒再上過課。科研中的編程,和計算機科學搞底層設計是不一樣的。其實科研的編程和搭建實驗裝置是一樣的,都是藉助各種已有的工具和材料,去實現一個目標中的功能。寫程序,其實不是在寫代碼,而是在寫邏輯,寫你抽象問題、拆分問題、解決問題的思路。編程絕對不是簡單的寫幾個 for loop!所以,如果你科研能做得好,經過一定的學習、代碼也一定能寫得好。如果你代碼一直寫不好,我要懷疑你是不是科研也面臨困境,甚至推廣而言、是不是你生活中解決問題的能力有待提高。
所以編程能力,是你的邏輯能力,是你解決問題的能力。這種能力不需要專門去學習編程的,生活中的一舉一動都是鍛煉。而編程經驗,就是選擇合適的程序語言和庫,寫出程序,自然就是在不斷使用中積累出來的。沒有什麼快捷的辦法。你需要知道有哪些工具可以用,才能想辦法去用,awareness是第一步。而自身的外部和內部的驅動力則是維持學習興趣的關鍵因素。譬如,外部來說,科研中需要做這樣那樣的操作,而且很多都有重複性,一定可以程序化。並且這些操作很可能現成的商業軟體里不是特別容易實現,那還不如自己編寫腳本。內部來說,鼓搗程序、學習語言本身也是很有趣的事情啊,不僅可以學到新的手法、讓電腦精確實現自己想要的功能,說不定還能體會到一些編程思想。比如模塊化,比如面向對象中的類和動作、繼承、封裝解決問題的能力沒有什麼具體好說的,各有各的招。下面就說說工具這塊,如何選擇語言並熟練使用。
程序語言方面,建議優先選擇一種高級腳本語言,比如 Python, Perl 或者 JavaScript。哦,matlab、Mathematica 和 R 也算的。作為科學計算的話,Python+numpy 確實是很好的免費 matlab 替代方案,而且 Python 語法清晰,import 大法也使得擴展非常方便。不建議選擇底層語言,比如 C 或者 Fortran。就像建築師不需要知道一塊磚頭是怎麼造出來的,組裝電腦也不需要知道集成電路裡面的電阻電容怎麼擺放的。你的精力有限,不要過早跳入底層實現的坑,那是CS專業做的事情。人家開發出來高級腳本語言,就是為了方便實現功能的。至於什麼腳本語言速度不夠快?哎,硬體界有個玩笑話,大意是程序員辛辛苦苦花了兩年優化了一個演算法,直接被下一代處理器虐成了渣,是吧。運行速度在大部分情景當中都不是問題。當然,Fortran作為一個專門的坑,有興趣的出門右轉去看地圖炮好了:和 C++ 相比,用 Fortran 編程是怎樣的體驗? - 王力樂的回答
學習方面,我很少去買大堆的參考書,或者在網上找什麼XX速成、XX教程。我始終認為,最好的資料就是該語言的開發者文檔,你應該儘早開始閱讀,並且經常反覆翻閱。
- 開發者文檔是這門語言最直接、最直白的說明。首先裡面的東西很全,你可以通過標籤快速瀏覽,大致了解這個程序語言、或者這個擴展模塊可以幹些什麼事情。這解決了 awareness 的問題。(速成書和網路課程里可能只會告訴你一小部分功能)
- 當你需要用到某個功能或工具時,開發者文檔中的例子往往就非常好、簡潔而且切中要害。
- 從開發者文檔的說明中,你不光可以看到工具的使用方法,還可以看到開發者開發這個語言或這個模塊的內在邏輯,可以體會到這個工具的獨特之處,然後舉一反三。
然後,善用 Google 和 stackoverflow 。我知道大天朝在這方面有些不便利,大家自己想辦法吧。
應用方面,前面說了,最好是有一個明確的目標作為外部驅動,而不是去刷教程裡面的作業。這樣不僅方向明確,程序寫成功之後也可以帶來實際的便利,刺激你大腦的獎勵機制。
在閱讀文檔、例子和實際編寫程序的過程中,要不斷地思考,有沒有更好的解決方案。一個問題可以有很多解決方案,你自己要有點追求,在能力範圍內,不斷追求尋找更好的用戶體驗、更簡短的代碼,並使用最佳的工具。
舉個閱讀的例子。你讀到 Python 的數據結構中有字典,一個鍵對應一個值。你馬上可以想到,這樣的結構一定可以用在很多需要對應關係的地方,比如模式或者錯誤類型。你又讀到 Python 的迭代機制,那你一定可以想到在需要做循環,但卻需要動態改變列表元素的時候,用迭代器來實現。
再舉個寫程序的例子。你的腳本中針對不同的情況需要修改一些參數。你當然可以很沒有追求的說,哎呀我每次運行前把腳本里對應的數字改一下好了。不過,這顯然是極為糟糕的用戶體驗。那你有沒有想過,能不能用 parser 把參數從終端輸入呢?參數太多的話,能不能讓程序讀入一個 input 文檔呢?更進一步,能不能讓程序自動判斷該使用何種參數設置呢?最後,你的腳本有沒有 error handling 呢?你肯定希望程序能 catch 明顯的錯誤,而不至於動不動就 crash 吧?
簡言之,就是得有點追求。在這樣的過程中,你會去搜索並學習到越來越多的工具和技巧。這就豐富了你的知識庫。----------
另外我覺得似乎得請一下大神 @王力樂和 @劉博洋
附下自己的背景和經歷:
我接觸編程的概念是中學時參加信息學競賽,那時候學的是 Pascal,擼過一點點演算法,限於中學生的理解力沒有深入太久。但是中學的經驗幫助我理解了一些最基本的概念:函數、指針、全局與局域變數、內存分配等等,了解這些概念是非常有幫助的。高中還玩過一陣 html,對文本標記也算是有一點了解。
你要指望從大學必修課程C裡面學到什麼乾貨是不可能的,本科的化學內容也用不到太多的編程,偶爾積分算不出來用 Mathematica 做一下弊而已,不足道。真正重新回到和代碼打交道是大四為了寫論文,開始學習 latex。
到研究生階段以後,一方面自己的工作涉及一些數據處理和作圖,需要自定義的函數和過程,你當然不希望所有的事情都在 Excel 裡面做;另一方面,考慮到國外搞盜版容易出事兒,自己又比較窮,沒錢買新電腦買軟體,直接轉到了 linux【這點其實是開玩笑啦】,正式進入自己動手豐衣足食的狀態至今。
在 linux 平台下,在終端中打指令實在是太方便太舒服了。數據的處理使用 Python+numpy,譜圖繪製用 gnuplot,給組裡維護 matlab 程序(這個是組裡出錢買的,我自己用 python 就好了啟動快),寫作用 latex。現在在鼓搗 GUI 因為想做個模擬器參數實在太多,還是需要一個 GUI 的
聰明人學學就會。我這樣的還得刷題。
推薦一個網站
Geeksforgeeks簡而言之,夠用就行,邊學邊用。遇到問題去查手冊或者請教別人,迅速解決當前的問題,這當中你已經學到了很多。然後有時間靜下心來學一些專業課程,長期積累會有質的提升(多一些角度看問題)。
下邊是絮叨:
先介紹下背景。我本身做軟凝聚態方面的理論,需要寫程序來求解分析問題。主要用到的是領域內一個合作者的基於C++的程序,規模比較大(我不知道多大算大,不過相對於我的水平已經夠規模了),主要演算法涉及一些常用的Minimizer和Monte Carlo。另外需要使用Python, Mathematica分析數據。同時Mathematica也用來解微分方程推倒公式。也會一些MATLAB,主要是解邊值問題的微分方程。因此,我能夠使用的工具基本是C++, Python, Mathematica, MATLAB, 以及寫論文都會用的LaTex。另外我本人也去聽了一些計算機系的課程,有一定的了解。
再說一下我對編程在基礎科學中的應用的看法。對於做物理的人來說,編程是把公式轉化成代碼,讓計算機幫你解方程,或者模擬一個系統(比如MC)。對於計算機系的人來說,需要考慮更多程序本身的問題,而不是任何物理意義。比如,做編程工作的不需要去考慮一個系統某個參數的物理意義:它的單位應該是什麼(如何dimensionless),和其他參數的關係,參數和物理模型的對應,考慮的更多的是,如果我要寫個大規模的程序,應該怎麼來搭建。對於做物理的,搭建的程序速度慢了個不大的常數不太要緊,能算,等得起就行。關鍵是我需要模擬的物理系統是什麼,然後如何把公式轉換成相應的代碼。總之,物理系的編程和計算機系的目的不一樣,因此沒必要用計算機系的標準要求你科研的代碼。思考模型遠比寫代碼重要。
如何學習和提高?首先要會一門程序語言,這個應該在本科的課程中都學過。您在這類課程中需要掌握的是知道這門語言的語法,編程的基本概念(比如C里的指針,Mathematica里的core language),以及遇見不熟悉的東西和問題如何查找答案,和基本的編程經驗,這就夠了。在科研中遇到寫不出來的演算法和沒掌握的語言,去查官方的幫助文件,看論壇,找教科書,都可以。在這個過程中您能學會其他的語言,找到適合您的編程工具,以及和您可以共同交流相互促進的科研夥伴。
如果你真的很想系統的學一些編程相關的知識,對自己有一個整體上的提高,那麼最好去選相應的課,而且心理做好準備:可能你花一年學下來四五門計算機專業課,也未必能對你的科研有所幫助。可如果你堅持做一些編程的工作,積累足夠的經驗,最後會對你的科研有相當的益處,但這需要很長的時間。
具體說幾點,也許跟問題沒有直接關聯。
您需要學什麼語言呢?一門你自己用的順手的,用來解決一些你手頭需要解決的小問題。其他的語言取決於你的合作者用什麼,領域裡常用的是什麼,你實驗室的人用什麼,這樣方便互相交流和提高。
您需要對演算法有多少了解呢?在科研之前可以什麼都不了解,需要用了再去學。比如您僅僅是用MC來做模擬,那就沒什麼必要精通PDE的數值解。如果突然有一天需要解一個PDE,您的老闆會推薦相應的軟體和方法,然後去學就好了。
您需要多強大的程序構建能力呢?我舉個例子:我們這邊有個博士後,他非常善於編寫程序,組裡的人可以從他那裡得到很多技術細節上的幫助,但是他物理上里的理解還不如組裡的研究生,因此也沒怎麼發paper。他的老闆人非常聰明,對物理有著深刻理解,做了很多年的解析,後來因為看到一些做計算的人在物理上有錯誤,就毅然決然自己開始學Fortran寫代碼。他自己的代碼風格相當差,不過能驗證他的想法,得到有意義的結果,從而對學界做出貢獻。您是想做相關基礎科學領域代碼寫的好的人呢(當然,如果真的是最好,很多人會來找你幫忙),還是想做一個相關領域有巨大貢獻的科學家呢?這兩者並不矛盾,側重哪一方取決於您對自己的定位。
我目前的工作就是做的基礎學科的編程,我所學的專業中可以說百分之八十的學生是需要用到計算的,雖然很多內容可以利用現有的商用軟體包直接計算,但很多時候仍然需要自己動手編程。我目前就是做的這個。
我本科學過VB、C++,matlab、mathematica也都學過,現在讀研重新學了fortran。我主要做的就是數值計算方面的工作,我的感受就是不論是用fortran還是C++(目前這兩種語言用的較多)一般的數值計算都只用到比較基礎的一些功能,不是做商用軟體的話那些高級功能一般用不上,matlab是不能用於規模比較大的計算的,但是matlab對於中小型的問題有著巨大的優勢,很多數值計算的內容都可以直接調用現有的庫函數,非常適合沒有經驗的使用者使用。
關於對編程的學習,肯定是要找一本比較好的書入門的,fortran的話推薦彭國倫那一本。之後就是要讀現有的代碼,理解並熟悉循環、判斷等常用語句。之後就可以自己開始編程了。對於一個需要長期編程的人來說,有許多代碼是需要積累的,比如常用的矩陣求逆的代碼,這樣要用到的時候直接添加而不必從新再寫,這樣編程的工作並不會很多。
個人覺得需要提醒初學者的是:對程序的整體結構需要在寫程序之前做一個初步的設計,也就是要有一個程序流程圖,搞清楚程序大概分成幾個模塊,每個模塊又分成幾個函數或子程序;一點要學會寫偽代碼,不認為有多少人能夠直接將頭腦中的東西變成代碼,所以還是現在紙上寫寫偽代碼吧。完成比完美更重要
從事基礎學科編程能力確實很重要提高編程能力可以從碎片時間做起
------------乾貨-------------
Stack Overflow 是個好地方經常逛逛,一些小tip可能在關鍵時候幫上大忙
GitHub · Where software is built 要會fork,關於自己感興趣的project,茶餘飯後看一看
CSDN.NET - 全球最大中文IT社區,為IT專業技術人員提供最全面的信息傳播和服務平台 這個是中文社區,很多很棒的資源除了碎片時間,關於主動鍛煉的方面,可以參加一些競賽,不一定是acm類的代碼競賽,也可以是數學建模啊,cupt啊之類的雖然學術氣息非常濃厚但是又很需要代碼功底的比賽,它們可以逼你在很短一段時間裡學到關於某個方面特別深入的代碼知識,同時,一些比賽對於數值模擬數據統計和可視化代碼量的硬性要求肯定是對編程能力有很大好處。
還可以偶爾腦子一熱想自己著手一些小project,比如說我(空間物理專業(也算比較基礎學科了)),突然有一天想做個手機應用,於是裝了個androidstudio,圖書館隨便借了本書,自己從頭寫ui造輪子半個月寫了個數據統計和擬合的手機app,比較粗糙,但是非常實用
關於本專業也偶爾寫一些總量千行級別的小project比如
用opencv的lucasd演算法加上數字圖像的一些處理實現的日冕物質拋射的 波前的動態識別和跟蹤
平常用matlab比較多,但也接觸了java,比較熟悉c++,python,但也不總用編程干正事,比如
很有趣,而且實現起來不是很困難
個人感覺編程能力提高不是一朝一夕的事情,但是提高到夠用還真花不了多長時間
前提是你要去做----------【完成比完美更重要】
不想著要做多好,做完就成,親身經歷就是非常想把一個project搞得非常好,結果加來加去,顯得非常臃腫而多bug樓主可以看看這個課程的outline:
High Performance Scientific Computing :https://class.coursera.org/scicomp-001/class/index
- Working at the command line in Unix-like shells (e.g. Linux or a Mac OSX terminal).
- Version control systems, particularly git, and the use of Github and Bitbucket repositories.
- Work habits for documentation of your code and reproducibility of your results.
- Interactive Python using IPython, and the IPython Notebook.
- Python scripting and its uses in scientific computing.
- Subtleties of computer arithmetic that can affect program correctness.
- How numbers are stored: binary vs. ASCII representations, efficient I/O.
- Fortran 90, a compiled language that is widely used in scientific computing.
- Makefiles for building software and checking dependencies.
- The high cost of data communication. Registers, cache, main memory, and how this memory hierarchy affects code performance.
- OpenMP on top of Fortran for parallel programming of shared memory computers, such as a multicore laptop.
- MPI on top of Fortran for distributed memory parallel programming, such as on a cluster.
- Parallel computing in IPython.
- Debuggers, unit tests, regression tests, verification and validation of computer codes.
- Graphics and visualization of computational results using Python.
我現在在移動互聯網方向創業,自己也寫過很多年的程序,還算是個合格的程序員,以我的經歷來講主要靠自學。
我之前念的是化工,後來轉到自動化,剛接觸的編程的時候就非常喜歡,相關的書籍仔細閱讀過很多,數據結構和演算法很重要,認真學習,研究一些習題挺重要的,這個對找工作很有幫助。
學習基本知識後就是實踐,我當時參加過編程比賽,比如自動化的電子設計大賽,百度的編程大賽;選修了一些課程,C++高級編程之類的,課程是什麼不重要,主要是大作業比較多,這樣可以系統的編寫軟體,另外,抓住一切可能的機會去實習,我去過聯想和幾個創業公司實習,在實習中對於編程水平的提升比較大,特別是同事如果是高人。我那個時候去實習,完全不計較報酬,每天幾乎是第一個去公司的,最後幾個走,晚上回學校還去圖書館查閱資料,提高非常大。
到大四之後,我和幾個同學開始做外包,我一邊編程一邊在網上找項目,在接項目的過程中,我找到了創業的方向,就開始混跡於移動互聯網。
這是我個人學習實踐編程的一些經歷,希望對你有幫助。
你通常不需要學C。Matlab足夠。這倆的難度不在一個級別上。
去http://LintCode.com做最新面試題。上九章演算法的課程。http://www.jiuzhang.com/?source=zhihu
雇一個程序員吧,給碼農的留份工作...
推薦閱讀:
※第六屆北斗導航年會剛剛結束,導航作為一個朝陽產業,那從事導航相關工作:比如演算法,待遇和發展到底如何?
※穆斯林師弟每天都在辦公室禱告如何能坦然接受?
※你的研究生導師有多好?
※在華南理工大學讀研是一種怎樣的體驗?
※浙江大學118周年了你想對他說什麼?