R語言程式設計導論

林嶔 (Lin, Chin)

Lesson 2 R條件判斷與迴圈

第一節:條件判斷式(1)

1 < 2
2 == 1 + 1
"Z" > "B"
x = c(1, 2, 3, 4, 5)
x <= 4
x > 2

第一節:條件判斷式(2)

x = c(1, 2, 3, 4, 5)
x <= 4 & x > 2
x > 4 | x <= 2

第一節:條件判斷式(3)

if ("Z" > "B") {x = 2} else {x = 5}
if ("利" > "弊") {y = 3} else {y = 4}
x * y

– 答案是不行的,因為函數「if」的括弧內僅能包含「一個」邏輯值(請同學試試)

x = c(1, 2, 3, 4, 5)
x[x <= 4 & x > 2] = -1
x

練習1:找尋滿足特定條件的位置

– 函數「which()」會將邏輯向量中為TRUE的位置回傳給我們

a = c(TRUE, FALSE, FALSE, TRUE, FALSE)
which(a)
x = c(15,86,55,36,94,55,97,12,61,1,20,71,61,19,6,60,17,39,75,61,20,17,96,10,84,1,32,39,50,72,59,24,
      33,19,14,86,41,25,97,55,5,29,82,24,7,80,94,55,27,72,69,52,67,100,98,80,1,35,4,65,26,26,66,99,
      2,88,2,4,40,26,50,61,80,15,6,97,64,70,26,74,43,34,83.3,20,29,55,27,22,43,45,82,28,71,80,45,5,
      57,71,48,48,36,24,91,28,76,12,73,43,7,47,77,60,9,56,57,61,27,79,8,40,55,60,64,40,96,76,49,88,
      18,65,35,37,85,76,44,48,85,11,53,41,46,76,40,11,41,74,31,20,80,94,87,4,10,33,41,24,100,38,84,
      1,68,52,43,26,4,12,23,31,32,12,39,1.9,79,58,56,72,88,78,5,61,10,35,31,84,81,90,6,68,11,17,73,
      95,43,25,27,87,59,56,20,79,80,75,65,64,14,62,78,83,83,4,99.7,97,47,40,64,1,96,60,85,27,42,43,
      16,33,89,12,83,2,86,33,64,44,64,18,78,18,54,8,55,46,9,44,6,3,6,47,94,90,46,78,71,92,42,41,54,
      37,60,58,28,62,85,79,100,70,41,96,89,56,82,42,17,60,99,40,92,68,98,6,84,41,44,80,49,49,18,70,
      30,45,71,83,61,26,63,76.9,98,34,13,73,44,23,37,8,78,98,85,75,98,49,77,9,47,85,16,86,20,12,98)

練習1答案

x %% 1

– 這樣就不難找了

which((x %% 1) != 0)
## [1]  83 172 211 294
which(as.integer(x) != x)
## [1]  83 172 211 294

第二節:迴圈(1)

x = c(1, 1)
x[3] = x[2] + x[1]
x[4] = x[3] + x[2]
x[5] = x[4] + x[3]
x[6] = x[5] + x[4]
x
## [1] 1 1 2 3 5 8

第二節:迴圈(2)

x = c(1, 1)

i = 3
x[i] = x[i-1] + x[i-2]

i = 4
x[i] = x[i-1] + x[i-2]

i = 5
x[i] = x[i-1] + x[i-2]

i = 6
x[i] = x[i-1] + x[i-2]

x
## [1] 1 1 2 3 5 8

第二節:迴圈(3)

– 在這裡我們需要兩個物件:物件「x」為儲存費波納奇數列的物件,而物件「indexes」代表著隨迴圈變化的物件

– 注意,在這裡我們第一次使用運算子「:」,而「3:20」表示從3到20的所有整數

x = c(1, 1)
indexes = 3:20
indexes
##  [1]  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20
for (i in indexes) {
  x[i] = x[i-1] + x[i-2]
}

x
##  [1]    1    1    2    3    5    8   13   21   34   55   89  144  233  377  610
## [16]  987 1597 2584 4181 6765

第二節:迴圈(4)

i = 3 #物件「indexes」中的第一個數字
x[i] = x[i-1] + x[i-2]
i = 4 #物件「indexes」中的第二個數字
x[i] = x[i-1] + x[i-2]
i = 20 #物件「indexes」中的最後一個數字
x[i] = x[i-1] + x[i-2]

第二節:迴圈(5)

x = c(1, 1)

for (i in 3:20) {
  x[i] = x[i-1] + x[i-2]
}

x
##  [1]    1    1    2    3    5    8   13   21   34   55   89  144  233  377  610
## [16]  987 1597 2584 4181 6765

第二節:迴圈(6)

– 函數「cat」的功能是將文字前後連接起來並輸出在Console視窗中

students = c("小華", "小明", "小王")
scores = c(100, 80, 70)

for (i in 1:3) {
  cat(students[i], "的考試成績為", scores[i], "分\n")
}
## 小華 的考試成績為 100 分
## 小明 的考試成績為 80 分
## 小王 的考試成績為 70 分

練習2:NDMC數列

– 而我們現在創造一個NDMC數列,其定義是起始數列為1、1,之後第三個數字(奇數)為前兩個相加,第四個數字(偶數)為前兩個數字相乘,第五個數字(奇數)為前兩個相加,依此類推。

y = c(1, 1)
y[3] = y[1] + y[2]
y[4] = y[2] * y[3]
y[5] = y[3] + y[4]
y[6] = y[4] * y[5]
y[7] = y[5] + y[6]
y[8] = y[6] * y[7]
y[9] = y[7] + y[8]
y[10] = y[8] * y[9]
y
##  [1]     1     1     2     2     4     8    12    96   108 10368

練習2答案(1)

y = c(1, 1)

i = 1
y[i+2] = y[i] + y[i+1]
i = 2
y[i+2] = y[i] * y[i+1]
i = 3
y[i+2] = y[i] + y[i+1]
i = 4
y[i+2] = y[i] * y[i+1]
i = 5
y[i+2] = y[i] + y[i+1]
i = 6
y[i+2] = y[i] * y[i+1]
i = 7
y[i+2] = y[i] + y[i+1]
i = 8
y[i+2] = y[i] * y[i+1]

y
y = c(1, 1)

for (i in 1:8) {
  if (i == '奇數') {
    y[i+2] = y[i] + y[i+1]
  } else {
    y[i+2] = y[i] * y[i+1]
  }
}

y

練習2答案(2)

y = c(1, 1)

for (i in 1:8) {
  if (i %% 2 == 1) {
    y[i+2] = y[i] + y[i+1]
  } else {
    y[i+2] = y[i] * y[i+1]
  }
}

y
y = c(1, 1)

for (i in 1:8) {
  if (as.integer(i/2) == i/2) {
    y[i+2] = y[i] + y[i+1]
  } else {
    y[i+2] = y[i] * y[i+1]
  }
}

y
y = c(1, 1)

for (i in 1:8) {
  if ((-1)^i == -1) {
    y[i+2] = y[i] + y[i+1]
  } else {
    y[i+2] = y[i] * y[i+1]
  }
}

y

練習2答案(3)

– 這個解法的關鍵在於,我們需要改變我們的索引數:

y = c(1, 1)

i = 1
y[2*i+1] = y[2*i-1] + y[2*i]
y[2*i+2] = y[2*i] * y[2*i+1]
i = 2
y[2*i+1] = y[2*i-1] + y[2*i]
y[2*i+2] = y[2*i] * y[2*i+1]
i = 3
y[2*i+1] = y[2*i-1] + y[2*i]
y[2*i+2] = y[2*i] * y[2*i+1]
i = 4
y[2*i+1] = y[2*i-1] + y[2*i]
y[2*i+2] = y[2*i] * y[2*i+1]

y
y = c(1, 1)

for (i in 1:4) {
  y[2*i+1] = y[2*i-1] + y[2*i]
  y[2*i+2] = y[2*i] * y[2*i+1]
}

y

第三節:多層次迴圈(1)

– 現在讓我們想辦法列出2:6內所有的「質數」

– 何謂質數?質數的定義為找不到比自己更小的可整除除數,如5以下的數字為2、3、4,而5無法被這些數字整除

– 現在讓我們思考該如何回答我們的問題…

第三節:多層次迴圈(2)

– 再使用函數「rep()」產生一個等長的物件answer.x表示物件x中相對應的元素是否為質數,而預設通通為TRUE

x = 2:6
answer.x = rep(TRUE, 5) #你也可以使用length(x)來替代5
#對3進行檢測(x物件中的第2個數字)
if (x[2] %% x[1] == 0) {answer.x[2] = FALSE}

#對4進行檢測(x物件中的第3個數字)
if (x[3] %% x[1] == 0) {answer.x[3] = FALSE}
if (x[3] %% x[2] == 0) {answer.x[3] = FALSE}
  
#對5進行檢測(x物件中的第4個數字)
if (x[4] %% x[1] == 0) {answer.x[4] = FALSE}
if (x[4] %% x[2] == 0) {answer.x[4] = FALSE}
if (x[4] %% x[3] == 0) {answer.x[4] = FALSE}
  
#對6進行檢測(x物件中的第5個數字)
if (x[5] %% x[1] == 0) {answer.x[5] = FALSE}
if (x[5] %% x[2] == 0) {answer.x[5] = FALSE}
if (x[5] %% x[3] == 0) {answer.x[5] = FALSE}
if (x[5] %% x[4] == 0) {answer.x[5] = FALSE}
x[answer.x]
## [1] 2 3 5

第三節:多層次迴圈(3)

#重新產生x與answer.x
x = 2:6
answer.x = rep(TRUE, 5)

#對3進行檢測(x物件中的第2個數字)
i = 2
if (x[i] %% x[1] == 0) {answer.x[i] = FALSE}

#對4進行檢測(x物件中的第3個數字)
i = 3
if (x[i] %% x[1] == 0) {answer.x[i] = FALSE}
if (x[i] %% x[2] == 0) {answer.x[i] = FALSE}
  
#對5進行檢測(x物件中的第4個數字)
i = 4
if (x[i] %% x[1] == 0) {answer.x[i] = FALSE}
if (x[i] %% x[2] == 0) {answer.x[i] = FALSE}
if (x[i] %% x[3] == 0) {answer.x[i] = FALSE}
  
#對6進行檢測(x物件中的第5個數字)
i = 5
if (x[i] %% x[1] == 0) {answer.x[i] = FALSE}
if (x[i] %% x[2] == 0) {answer.x[i] = FALSE}
if (x[i] %% x[3] == 0) {answer.x[i] = FALSE}
if (x[i] %% x[4] == 0) {answer.x[i] = FALSE}

#顯示所有質數
x[answer.x]
## [1] 2 3 5

第三節:多層次迴圈(4)

#重新產生x與answer.x
x = 2:6
answer.x = rep(TRUE, 5)

#對3進行檢測(x物件中的第2個數字)
i = 2
j = 1
if (x[i] %% x[j] == 0) {answer.x[i] = FALSE}

#對4進行檢測(x物件中的第3個數字)
i = 3
j = 1
if (x[i] %% x[j] == 0) {answer.x[i] = FALSE}
j = 2
if (x[i] %% x[j] == 0) {answer.x[i] = FALSE}
  
#對5進行檢測(x物件中的第4個數字)
i = 4
j = 1
if (x[i] %% x[j] == 0) {answer.x[i] = FALSE}
j = 2
if (x[i] %% x[j] == 0) {answer.x[i] = FALSE}
j = 3
if (x[i] %% x[j] == 0) {answer.x[i] = FALSE}
  
#對6進行檢測(x物件中的第5個數字)
i = 5
j = 1
if (x[i] %% x[j] == 0) {answer.x[i] = FALSE}
j = 2
if (x[i] %% x[j] == 0) {answer.x[i] = FALSE}
j = 3
if (x[i] %% x[j] == 0) {answer.x[i] = FALSE}
j = 4
if (x[i] %% x[j] == 0) {answer.x[i] = FALSE}

#顯示所有質數
x[answer.x]
## [1] 2 3 5

第三節:多層次迴圈(5)

#對6進行檢測(x物件中的第5個數字)
i = 5
j = 1
if (x[i] %% x[j] == 0) {answer.x[i] = FALSE}
j = 2
if (x[i] %% x[j] == 0) {answer.x[i] = FALSE}
j = 3
if (x[i] %% x[j] == 0) {answer.x[i] = FALSE}
j = 4
if (x[i] %% x[j] == 0) {answer.x[i] = FALSE}
#對6進行檢測(x物件中的第5個數字)
i = 5
for (j in 1:4) {
  if (x[i] %% x[j] == 0) {answer.x[i] = FALSE}
}

第三節:多層次迴圈(6)

#重新產生x與answer.x
x = 2:6
answer.x = rep(TRUE, 5)

#對3進行檢測(x物件中的第2個數字)
i = 2
for (j in 1:1) {
  if (x[i] %% x[j] == 0) {answer.x[i] = FALSE}
}

#對4進行檢測(x物件中的第3個數字)
i = 3
for (j in 1:2) {
  if (x[i] %% x[j] == 0) {answer.x[i] = FALSE}
}
  
#對5進行檢測(x物件中的第4個數字)
i = 4
for (j in 1:3) {
  if (x[i] %% x[j] == 0) {answer.x[i] = FALSE}
}
  
#對6進行檢測(x物件中的第5個數字)
i = 5
for (j in 1:4) {
  if (x[i] %% x[j] == 0) {answer.x[i] = FALSE}
}

#顯示所有質數
x[answer.x]
## [1] 2 3 5

第三節:多層次迴圈(7)

#重新產生x與answer.x
x = 2:6
answer.x = rep(TRUE, 5)

#對3進行檢測(x物件中的第2個數字)
i = 2
for (j in 1:(i-1)) {
  if (x[i] %% x[j] == 0) {answer.x[i] = FALSE}
}

#對4進行檢測(x物件中的第3個數字)
i = 3
for (j in 1:(i-1)) {
  if (x[i] %% x[j] == 0) {answer.x[i] = FALSE}
}
  
#對5進行檢測(x物件中的第4個數字)
i = 4
for (j in 1:(i-1)) {
  if (x[i] %% x[j] == 0) {answer.x[i] = FALSE}
}
  
#對6進行檢測(x物件中的第5個數字)
i = 5
for (j in 1:(i-1)) {
  if (x[i] %% x[j] == 0) {answer.x[i] = FALSE}
}

#顯示所有質數
x[answer.x]
## [1] 2 3 5

練習3:親手做出多層次迴圈

– 請你試著理解剛剛的每個過程,並找出100以下的質數有哪些。

– 但事實上質數可以再更精確的定義為找不到比自己更小的可整除的「質數」,如5以下的「質數」為2、3,因此在檢查5的時候我們其實不需要檢查4這個數字

練習3答案(1)

#重新產生x與answer.x
x = 2:6
answer.x = rep(TRUE, 5)

#i與j的組合迴圈
for (i in 2:5) {
  for (j in 1:(i-1)) {
    if (x[i] %% x[j] == 0) {answer.x[i] = FALSE}
  }
}

#顯示所有質數
x[answer.x]
## [1] 2 3 5

練習3答案(2)

#重新產生x與answer.x
x = 2:100
answer.x = rep(TRUE, 99)

#i與j的組合迴圈
for (i in 2:99) {
  for (j in 1:(i-1)) {
    if (x[i] %% x[j] == 0) {answer.x[i] = FALSE}
  }
}

#顯示所有質數
x[answer.x]
##  [1]  2  3  5  7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97

練習3引申

– 我們其實只要檢查比\(\sqrt{n}\)更小的質數就好,並且如果遇到已經發現他不是質數了就可以跳過(使用「break」)!

x = 2:5000
answer.x = rep(TRUE, 4999)

for (i in 2:4999) {
  n = x[i]
  chech_n = as.integer(sqrt(n))
  for (j in 1:chech_n) {
    if (answer.x[j] == TRUE) {
      if (x[i] %% x[j] == 0) {
        answer.x[i] = FALSE
        break
      }
    }
  }
}

小結

– 本節課學到功能如下,同學務必熟悉本次課程的內容:

  1. if/else功能
  2. 索引函數與條件判斷的組合
  3. 迴圈運算