第四講-程序設(shè)計.ppt_第1頁
第四講-程序設(shè)計.ppt_第2頁
第四講-程序設(shè)計.ppt_第3頁
第四講-程序設(shè)計.ppt_第4頁
第四講-程序設(shè)計.ppt_第5頁
已閱讀5頁,還剩31頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、1、程序設(shè)計方法 2、應(yīng)用實例 3、實驗作業(yè),實驗內(nèi)容,學(xué)習(xí)R語言中程序設(shè)計方法,實驗?zāi)康?程序設(shè)計,程序控制結(jié)構(gòu),R是一個表達(dá)式語言(expression language),其任何一個語句都可以看成是一個表達(dá)式。表達(dá)式之間以分號分隔或用換行分隔。表達(dá)式可以續(xù)行,只要前一行不是完整表達(dá)式(比如末尾是加減乘除等運(yùn)算符,或有未配對的括號)則下一行為上一行的繼續(xù)。 若干個表達(dá)式可以放在一起組成一個復(fù)合表達(dá)式,作為一個表達(dá)式使用。組合用大括號表示,如: + x - 15; + x; 1 15 R語言也提供了其它高級程序語言共有的分支、循環(huán)等程序控制結(jié)構(gòu)。,分支結(jié)構(gòu) (if/else、switch語言

2、)if/else語句,分支結(jié)構(gòu)包括if結(jié)構(gòu): if (條件) 表達(dá)式1 或 if (條件) 表達(dá)式1 else 表達(dá)式2 其中的“條件”為一個標(biāo)量的真或假值,表達(dá)式可以是用大括號包圍的復(fù)合表達(dá)式。有else 子句時一般寫成: if(條件) 表達(dá)式組 else 表達(dá)式組 這樣的寫法可以使else不至于脫離前面的if。,例如,如果變量lambda為缺失值就給它賦一個缺省值,可用: if(is.na(lambda) lambda if (all(x0) 注意“ if (x0) value value 1 ZERO,switch語句,switch是多分支語句,其用法為: switch (stateme

3、nt, list); statement是一個表達(dá)式,list是列表,也可以用有名定義。根據(jù)表達(dá)式與list的關(guān)系返回一個值。如果表達(dá)式返回值屬于1:length(list)中的一個,則返回list中相應(yīng)位置的值,否則返回NULL。 a a x a a - switch (4, 2+2, mean(1:10), rnorm(4); a 1 NULL,當(dāng)list是有名定義時,statement等于變量名時,返回該變量名所對應(yīng)的值,否則返回NULL x a x a - switch (x, fruit=apple, drink=coffee, vegetable=broccoli); a 1 NU

4、LL,循環(huán)結(jié)構(gòu)(for/while/repeat)for語句,循環(huán)結(jié)構(gòu)中常用的是for循環(huán),是對一個向量或列表的逐次處理,格式為 for( name in values) expression 如:求1到100的和 sum-0; for(i in 1:100) sum-sum+i; i-i+1 sum; 1 5050,當(dāng)然,如果只是要求各元素的和,只要調(diào)用sum(x)即可。所以,編寫程序要精簡,應(yīng)盡量避免使用顯式循環(huán)。 我們再舉一個例子。比如,我們要計算同生日的概率。假設(shè)一共有365個生日(只考慮月、日),而且各生日的概率是相等的(這里忽略了閏年的情況以及可能存在的出生日期分布的不均勻)。設(shè)一

5、個班有n個人,當(dāng)n大于365時至少兩個人生日相同是必然事件。當(dāng)n小于等于365時,我們可以計算P至少有兩人同生日= 1 - Pn個人生日彼此不同,這時,n個人的生日可取值數(shù)為365n ,而n個人彼此不同的可能數(shù)為365中取n個的排列數(shù),彼此不同的概率為P3n65 。因此,為了計算n1,2,.,365的情況下的同生日概率,可以用如下循環(huán)實現(xiàn):, x = numeric(365) for(i in 1:365) xi= 1 for(j in 0:(i-1) xi= xi * (365-j)/365 xi x for(n in 1:365) xn =1 - prod(365:(365-n+1)/36

6、5) 這段程序只用了1秒。注意不能直接去計算365!,這會 超出數(shù)值表示范圍。,我們有時候需要在某個判定條件成立的時候開始循環(huán),一旦條件不成立,就終止循環(huán),這時可以用while循環(huán)語句。 while循環(huán)是在開始處判斷循環(huán)條件的,用法為: while (condition) expression 表示在condition成立的時候,執(zhí)行expression。 例:一段二分法解方程的程序。 eps while(b-aeps) c 0) b - c else a - c ,while語句,例:1000以內(nèi)Fibonacci數(shù)列的生成 f while(fi+fi+1 f 1 1 1 2 3 5 8 1

7、3 21 34 55 89 144 13 233 377 610 987,repeat語句是while不一樣,把條件加在末尾,依賴break命令跳出循環(huán),基本用法是: repeat expressions; if (condition) break 表示一直重復(fù)表達(dá)式的計算,知道condition成立的時候,跳出循環(huán)。,repeat語句,例(續(xù)):用repeat語句生成1000以內(nèi)Fibonacci數(shù)列 f repeat fi+2 =1000) break; f 1 1 1 2 3 5 8 13 21 34 55 89 144 13 233 377 610 987,編寫自己的函數(shù),R允許用戶創(chuàng)

8、建自己的函數(shù)。事實上,R本身提供的絕大多數(shù)函數(shù)如sum(), plot()等,是編寫人員寫在R中的,與用戶自己創(chuàng)建的函數(shù)沒有本質(zhì)上的區(qū)別。 R中函數(shù)定義的一般格式為 hello = function() cat(Hello, worldn) ;, hello #查看函數(shù)具體內(nèi)容 function () cat(Hello, worldn); hello() #運(yùn)行函數(shù) Hello, world 函數(shù)體為一個復(fù)合表達(dá)式,各表達(dá)式的之間用換行或分號分開。不帶括號調(diào)用函數(shù)顯示函數(shù)定義,而不是調(diào)用函數(shù)。 在命令行輸入函數(shù)程序很不方便修改,所以我們一般是打開一個其他的編輯程序

9、(如Windows 的記事本),輸入以上函數(shù)定義,保存文件,比如保存到了C:Rhello.R,我們就可以用 source(“Hi.R) 運(yùn)行文件中的程序。實際上,用source()運(yùn)行的程序不限于函數(shù)定義,任何R程序都可以用這種方式編好再運(yùn)行,效果與在命令行直接輸入是一樣的。,對于一個已有定義的函數(shù),可以用fix()函數(shù)來修改,如: fix(hello) 將打開一個編輯窗口顯示函數(shù)的定義,修改后關(guān)閉窗口函數(shù)就被修改了。fix()調(diào)用的編輯程序缺省為記事本,可以用“options(editor=編輯程序名)”來指定自己喜歡的編輯程序。 函數(shù)可以帶參數(shù),可以返回值,例如: larger x); x

10、y.is.bigger - yy.is.bigger; x; 這個函數(shù)輸入兩個向量(相同長度)x和y,然后把x中比y對應(yīng)元素小的元素替換為y中對應(yīng)元素,返回x的值。R返回值為函數(shù)體的最后一個表達(dá)式的值,不需要使用return()函數(shù)。不過,也可以使用“return()”函數(shù)從函數(shù)體返回調(diào)用者。,參數(shù)(自變量),R函數(shù)調(diào)用方式很靈活,例如,如下函數(shù): fsub =function(x, y) x-y 有兩個虛參數(shù)x和y,我們用它計算100-45,可以調(diào)用fsub(100,45),或fsub(x=100,y=45) ,或fsub(y=45, x=100),或fsub(y=45, 100)。即調(diào)用時

11、實參與虛參可以按次序結(jié)合,也可以直接指定虛參名結(jié)合。實參先與指定了名字的虛參結(jié)合,沒有指定名字的按次序與剩下的虛參結(jié)合。 函數(shù)在調(diào)用時可以不給出所有的實參,這需要在定義時為虛參指定缺省值。例如上面的函數(shù)改為: fsub = function(x, y=0) x-y 則調(diào)用時除了可以用以上的方式調(diào)用外還可以用fsub(100),fsub(x=100)等方式調(diào)用,只給出沒有缺省值的實參。,即使沒有給虛參指定缺省值也可以在調(diào)用時省略某個虛參,然后函數(shù)體內(nèi)可以用missing() 函數(shù)判斷此虛參是否有對應(yīng)實參,如: trans = function(x, scale) if(!missing(scal

12、e) x = scale*x 此函數(shù)當(dāng)給了scale的值時對自變量x乘以此值,否則保持原值。這種用法在其它語言中是極其少見的,R可以實現(xiàn)這一點(diǎn)是因為R的函數(shù)調(diào)用在用到參數(shù)的值時才去計算這個參數(shù)的值(稱為“懶惰求值”),所以可以在調(diào)用時缺少某些參數(shù)而不被拒絕。 R函數(shù)還可以有一個特殊的“.”虛參,表示所有不能匹配的實參,調(diào)用時如果有需要與其它虛參結(jié)合的實參必須用“虛參名”的格式引入。例如: fmin fmin(c(5,1,2), c(9, 4, 7) 1 1 4,作用域,函數(shù)的虛參完全是按值傳遞的,改變虛參的值不能改變對應(yīng)實參的值。例如: x = c(1, abc) x 1 1 “abc f =

13、function(x) x2 f(x) 1 1 ! x 1 1 “abc 這個例子說明了函數(shù)體內(nèi)部的變量是局部的,賦值只針對函數(shù)體的變量,一旦函數(shù)運(yùn)行結(jié)束以后,不改變?nèi)肿兞康闹怠?函數(shù)體內(nèi)的變量也是局部的,對函數(shù)體內(nèi)的變量賦值當(dāng)函數(shù)結(jié)束運(yùn)行后變量值就刪除了,不影響原來同名變量的值。例如: x f f() 1 2 x 1 2 這個例子中原來有一個變量x值為2,函數(shù)中為變量x賦值20,但函數(shù)運(yùn)行完后原來的x值并未變化。但是也要注意,函數(shù)中的顯示函數(shù)調(diào)用時局部變量x還沒有賦值,顯示的是全局變量x 的值。這是R編程比較容易出問題的地方:你用到了一個局部變量的值,你沒有意識到這個局部變量還沒有賦值,而

14、程序卻沒有出錯,因為這個變量已有全局定義。,R程序設(shè)計注意要點(diǎn),對于復(fù)雜一些的計算問題我們應(yīng)該編寫成函數(shù)。這樣做的好處是 編寫一次可以重復(fù)使用,并且可以很容易地修改 函數(shù)內(nèi)的變量名是局部的,運(yùn)行函數(shù)不會使函數(shù)內(nèi)的局部變量被保存到當(dāng)前的工作空間,可以避免在交互狀態(tài)下直接賦值定義很多變量使得工作空間雜亂無章。,編寫函數(shù)是要注意: 可讀性(readability). 可理解性(understandability). 具體要做到: 采用結(jié)構(gòu)化、模塊化編程; 增加必要的注釋; 使用意義明確的名字作為變量名,切忌用人名或者寵物名; 行前縮進(jìn),使程序有層次感。,工作空間管理,R在運(yùn)行時保持一個變量搜索路徑表

15、,要讀取某變量時依次在此路徑表中查找,返回找到的第一個;給變量賦值時在搜索路徑的第一個位置賦值。但是,在函數(shù)內(nèi)部,搜索路徑表第一個位置是局部變量名空間,所以變量賦值是局部賦值,被賦值的變量只在函數(shù)運(yùn)行期間有效。 用ls()函數(shù)可以查看當(dāng)前工作空間保存的變量和函數(shù),用rm()函數(shù)可以剔除不想要的對象。如: ls()(或objects()),1 A Ai b cl cl.f fit1 g1 marks ns 10 p1 rec tmp.x x x1 x2 x3 y rm(x, x1, x2, x3) ls() 1 A Ai b cl cl.f fit1 g1 marks ns 10 p1 rec

16、tmp.x y ls()可以指定一個pattern參數(shù),此參數(shù)定義一個匹配模式,只返回符合模式的對象名。模式格式是UNIX中g(shù)rep的格式。比如,ls(pattern=tmp.)可以返回所有以“tmp.” 開頭的對象名。 rm()可以指定一個名為list的參數(shù)給出要刪除的對象名,所以rm(list=ls(pattern=“tmp.”) 可以刪除所有以“tmp.”開頭的對象名。 rm(list=ls() 刪除所有對象。,程序設(shè)計舉例,設(shè)計R程序是很容易的,在初學(xué)時我們只要使用我們從一般程序設(shè)計中學(xué)來的知識并充分利用R中現(xiàn)成的各種算法及繪圖函數(shù)就可以了。但是,如果要用R編制計算量較大的程序,或者程

17、序需要發(fā)表,就需要注意R程序設(shè)計的一些技巧。 用R語言開發(fā)算法,最重要的一點(diǎn)是要記住R是一個向量語言,計算應(yīng)該盡量通過向量、矩陣運(yùn)算來進(jìn)行,或者使用R提供的現(xiàn)成的函數(shù),避免使用顯式循環(huán)。顯式循環(huán)會大大降低R的運(yùn)算速度,因為R是解釋執(zhí)行的。,n=1:10; x=sin(n*pi/10); cat(x=,x) 1 x= 0.309017 0.5877853 0.809017 0.9510565 1 0.9510565 0.809017 0.5877853 0.309017 1.224606e-16 fsin - function(x) sin - 0; for ( i in 1:length(x)

18、 sini - sin(xi*pi/10); return(sin); y - 1:10; fsin(y); 1 3.090170e-01 5.877853e-01 8.090170e-01 9.510565e-01 1.000000e+00 6 9.510565e-01 8.090170e-01 5.877853e-01 3.090170e-01 1.224606e-16,例 對n=1,2,10,求xn= 的值,Money.R money=10000 years=0 while (money20000) years=years+1; money=money*(1+2.52/100) ,例 設(shè)

19、銀行年利率為2.52%。將10000元錢存入銀行,問至少多長時間會連本帶利翻一番?, source(Money.R); years; money; 1 28 1 20074.31, fun1=xx12+1; yx fun(c(1,2,3) 1 fun= 2 5 10,例,存款函數(shù)deposit() deposit - function(amount, total) if(amount = 0) stop (Deposits must be positive!n) total - total + amount; cat (amount, deposited. Your balance is, total, nn); ,例 考慮一個簡單的銀行存取款系統(tǒng),取款函數(shù)withdraw() withdraw total) stop (Sorry, you dont have that muc

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論