sp-4. 条件式

-- Views

January 26, 22

スライド概要

(Scheme プログラミング)
URL: https://www.kkaneko.jp/cc/scheme/index.html

profile-image

金子邦彦(かねこくにひこ) 福山大学・工学部・教授 ホームページ: https://www.kkaneko.jp/index.html 金子邦彦 YouTube チャンネル: https://youtube.com/user/kunihikokaneko

シェア

埋め込む »CMSなどでJSが使えない場合

各ページのテキスト
1.

sp-4. 条件式 (Scheme プログラミング) URL: https://www.kkaneko.jp/cc/scheme/index.html 金子邦彦 1

2.

アウトライン 4-1 条件式 4-2 パソコン演習 4-3 課題 2

3.

4-1 条件式 3

4.

• 条件式を使って,より役に立つプログラムを 作れるようになる. • 比較演算 (<,<=,>,>=,=) • 条件式のキーワード: cond, else • 奇数,偶数の判定(odd?, even?) • 論理演算 (and, or, not) 4

5.

比較演算 演算子 < <= > >= = 意味 より小さい 以下 より大きい 以上 等しい 5

6.

比較演算 (= x y) (< x y) (> x y) (<= x y) (>= x y) 数式 意味 x=y x<y x>y x≦y x≧y x is equal to y x is less than y x is greater than y x is less than and equal to y x is greater than and equal to y 6

7.

比較演算を実行してみると 比較演算では,条件が成り立てば true, 成り立たなければ false となる 7

8.

コンピュータが行っていること Scheme の式 例えば: (= 100 50) を入力する と・・・ コンピュータ (Scheme 搭載) 式の実行結果 false が表示される 8

9.

関数の中で比較演算を行ってみると ここでは, (define (is-child age) (< age 12)) という関数を作ってみた 実行結果として, true, false の値が 得られている 9

10.

よくある間違い • 「≦」,「≧」を使うことはできない これは間違い [(≦ amount 1000) 0.040] 正しくは [(<= amount 1000) 0.040] 10

11.

条件式の例 (define (interest-rate amount) (cond [(<= amount 1000) 0.040] [(<= amount 5000) 0.045] [(> amount 5000) 0.050])) この部分で 1つの大きな式 amount の値によって,結果が変わってくる ⇒ 条件式と呼ばれる由来 11

12.

条件式の例 (define (interest-rate amount) (cond [(<= amount 1000) 0.040] [(<= amount 5000) 0.045] [(> amount 5000) 0.050])) 条件の並び 12

13.

条件式での判定順 (define (interest-rate amount) 判定順 (cond [(<= amount 1000) 0.040] ① [(<= amount 5000) 0.045] ② ③ [(> amount 5000) 0.050])) • cond 文に並んだ複数の「条件」は,上から順に判定され る 上の例では,①,②,③の順に判定が行われ, ①が成り立てば,②,③は判定されない ②が成り立てば,③は判定されない • 「条件」の並んだ順序に意味がある 13

14.

else の使用例 (define (interest-rate amount) (define (interest-rate amount) (cond (cond [(<= amount 1000) 0.040] [(<= amount 1000) 0.040] [(<= amount 5000) 0.045] [(<= amount 5000) 0.045] [(> amount 5000) 0.050])) [else 0.050])) この2つは,結局は 同じことを行っている else とは 「上記の条件がどれも成り立たなければ」という意味 ★ else の方が,自分にとって分かりやすければ,else を使う 14

15.

even? • even? の意味: • 偶数ならば true (さもなければ false) 15

16.

論理演算 (and A B) A かつ B 例) (and (= x y) (< y z)) (or A B) A または B 例) (or (= x y) (< x z)) (not A) Aでない 例) (not (= x y)) 真,偽に関する論理的な演算を行う. 16

17.

条件式での「条件」として書けるもの 「true, false の値をとるもの」なら,何でも書くこと ができる • 比較演算 (<,<=,>,>=,=) 例: (<= amount 1000), (<= amount 5000), (> amount 5000), (= (remainder year 400) 0) • 奇数,偶数の判定(odd?, even?) 例: (odd? k), (is-leap? k) • true, false 値を出力とするような関数 例: (is-child a) • and, or, not による組み合わせ 例: (or (= m 1) (= m 2)), (not (= a 0)) など 但し,is-child が例えば 次のように定義されていること (define (is-child age) (< age 12)) 17

18.

Scheme の式の構成要素 • 数値: • 5, -5, 0.5 など • true, false 値 true, false • • 変数名 • • 四則演算子: +, -, *, / • • 比較演算子 <, <=, >, >=, = • 奇数か偶数かの判定 odd?, even? • 論理演算子 and, or, not • その他の演算子: remainder, quotient, max, min, abs, sqrt, expt, log, sin, cos, tan asin, acos, atan など 括弧 (, ), [, ] 関数名 define cond 18

19.

4-2 パソコン演習 19

20.

パソコン演習の進め方 • 資料を見ながら,「例題」を行ってみる • 各自,「課題」に挑戦する • 自分のペースで先に進んで構いません 20

21.

DrScheme の使用 • DrScheme の起動 プログラム • → PLT Scheme → DrScheme 今日の演習では「Intermediate Student」 に設定 Language → Choose Language → Intermediate Student → Execute ボタン 21

22.

例題1.条件式 • 残高 amount から利率を求める関数 interest-rate を作り,実行する • 残高が $1000 以下ならば: 4% • 残高が $5000 以下ならば: 4.5% • 残高が $5000より多ければ: 5% • 残高を条件とする条件式を使う • cond 句が登場 22

23.

例題1.条件式 利率 0.05 0.045 0.04 0 1000 5000 残高 23

24.

「例題1.条件式」の手順 1. 次を「定義用ウインドウ」で,実行しなさい • 入力した後に,Execute ボタンを押す ;; interest-rate: number -> number ;; to determine the interest rate ;; for the given amount (define (interest-rate amount) (cond [(<= amount 1000) 0.040] [(<= amount 5000) 0.045] [(> amount 5000) 0.050])) 2. その後,次を「実行用ウインドウ」で実行しなさい (interest-rate 1000) ☆ 次は,例題2に進んでください 24

25.

まず,Scheme のプログラムを コンピュータに読み込ませている 25

26.

ここでは, (interest-rate 1500) と書いて,amount の値を 1500 に設定しての実行 実行結果である「0.045」が 表示される 26

27.

今度は, (interest-rate 6000) と書いて,amount の値を 6000 に設定しての実行 実行結果である「0.05」が 表示される 27

28.

入力と出力 1500 0.045 interest-rate 入力 出力 28

29.

interest-rate 関数 「関数である」ことを 示すキーワード 関数の名前 (define (interest-rate amount) (cond [(<= amount 1000) 0.040] [(<= amount 5000) 0.045] [(> amount 5000) 0.050])) 1つの関数 値を1つ受け取る(入力) amount の値から 利率を求める(出力) 29

30.

条件式のプログラム (define (interest-rate amount) (cond amount ≦ 1000 のとき [(<= amount 1000) 0.040] [(<= amount 5000) 0.045] 1000 < amount ≦ 5000 のとき [(> amount 5000) 0.050])) 5000 < amount のとき 条件式 30

31.

比較演算の例 「amount ≦ 1000」の意味 (define (interest-rate amount) (cond [(<= amount 1000) 0.040] [(<= amount 5000) 0.045] [(> amount 5000) 0.050])) 31

32.

条件式の判定順 (define (interest-rate amount) 判定順 (cond [(<= amount 1000) 0.040] ① [(<= amount 5000) 0.045] ② ③ [(> amount 5000) 0.050])) • cond 文に並べた条件式は,上から順に判定される 上の例では,①,②,③の順に判定が行われ, ①が成り立てば,②,③は判定されない ②が成り立てば,③は判定されない • 条件式の並んだ順序に意味がある 32

33.

字下げを忘れないこと • 字下げを忘れると • プログラムは動くが,読みづらい (define (interest-rate amount) (cond [(<= amount 1000) 0.040] [(<= amount 5000) 0.045] [(> amount 5000) 0.050])) 字下げ 33

34.

例題2.ステップ実行 • 関数 interest-rate (例題1)について,実行結果 に至る過程を見る • (interest-rate 1500) から 0.045 に至る過程を見る • DrScheme の stepper を使用する (define (interest-rate amount) (cond [(<= amount 1000) 0.040] [(<= amount 5000) 0.045] [(> amount 5000) 0.050])) (interest-rate 1500) = (cond [(<= 1500 1000) 0.040] [(<= 1500 5000) 0.045] [(> 1500 5000) 0.050]) = (cond [false 0.040] [(<= 1500 5000) 0.045] [(> 1500 5000) 0.050]) = (cond [(<= 1500 5000) 0.045] [(> 1500 5000) 0.050]) = (cond [true 0.045] [(> 1500 5000) 0.050]) = 0.045 34

35.

「例題2.ステップ実行」の手順 1. 次を「定義用ウインドウ」で,実行しなさい • • Intermediate Student で実行すること 入力した後に,Execute ボタンを押す ;; interest-rate: number -> number ;; to determine the interest rate ;; for the given amount (define (interest-rate amount) (cond [(<= amount 1000) 0.040] [(<= amount 5000) 0.045] [(> amount 5000) 0.050])) (interest-rate 1500) 例題1と同じ 例題1に 1行書き加える 2. DrScheme を使って,ステップ実行の様子を 確認しなさい (Step ボタン,Next ボタンを使用) • 理解しながら進むこと ☆ 次は,例題3に進んでください 35

36.

(interest-rate 1500) から 0.045 が得られる過程 (interest-rate 1500) 最初の式 = (cond (cond [(<= 1500 1000) 0.040] [(<= amount 1000) 0.040] [(<= 1500 5000) 0.045] [(<= amount 5000) 0.045] [(> amount 5000) 0.050]) [(> 1500 5000) 0.050]) に amount = 1500 が代入される = (cond [false 0.040] [(<= 1500 5000) 0.045] (<= 1500 1000) → false [(> 1500 5000) 0.050]) = (cond [(<= 1500 5000) 0.045] [false 0.040] → 消える [(> 1500 5000) 0.050]) = (cond (<= 1500 5000) → true [true 0.045] コンピュータ内部での計算 [(> 1500 5000) 0.050]) 36 = 0.045 実行結果

37.

(interest-rate 1500) から 0.045 が得られる過程 (interest-rate 1500) = (cond [(<= 1500 1000) 0.040] [(<= 1500 5000) 0.045] [(> 1500 5000) 0.050]) = (cond [false 0.040] これは, [(<= 1500 5000) 0.045] (define (interest-rate amount) [(> 1500 5000) 0.050]) = (cond (cond [(<= amount 1000) 0.040] [(<= 1500 5000) 0.045] amount 5000) 0.045] [(> 1500[(<= 5000) 0.050]) = (cond [(> amount 5000) 0.050])) [true 0.045] を 1500 で置き換えたもの の amount [(> 1500 5000) 0.050]) = 0.045 37

38.

例題3.月の日数 • 月 month から,日数を求めるプログラ ム easy-get-num-of-days を書く.ここ では、うるう年のことは考えない • 比較演算と論理演算を組み合わせる 38

39.

「例題3.月の日数」の手順 1. 次を「定義用ウインドウ」で,実行しなさい (define (easy-get-num-of-days month) (cond [(= month 2) 28] [(or (= month 4) (= month 6) (= month 9) (= month 11)) 30] [else 31])) 2. その後,次を「実行用ウインドウ」で実行しなさい (easy-get-num-of-days 1) (easy-get-num-of-days 2) (easy-get-num-of-days 3) (easy-get-num-of-days 4) ☆ 次は,例題4に進んでください 39

40.

まず,Scheme のプログラムを コンピュータに読み込ませている 40

41.

ここでは, (easy-get-num-of-days 1) と書いて,month の値を 1 に設定しての実行 実行結果である「31」が 表示される 41

42.

入力と出力 1 31 easy-get-num-of-days 入力 入力は 1つの数値 出力 出力は 1つの数値 42

43.

easy-get-num-of-days 関数 「関数である」ことを 関数の名前 示すキーワード (define (easy-get-num-of-days month) (cond [(= month 2) 28] [(or (= month 4) (= month 6) (= month 9) (= month 11)) 30] [else 31])) 値を1つ受け取る(入力) 43

44.

例題4.ステップ実行 • 関数 easy-get-num-of-days (例題3)につ いて,実行結果に至る過程を見る • (easy-get-num-of-days 1) から 31 に至る過程を見 る • DrScheme の stepper を使用する (define (easy-get-num-of-days month) (cond [(= month 2) 28] [(or (= month 4) (= month 6) (= month 9) (= month 11)) 30] [else 31])) 44

45.

「例題4.ステップ実行」の手順 1. 次を「定義用ウインドウ」で,実行しなさい • • Intermediate Student で実行すること 入力した後に,Execute ボタンを押す (define (easy-get-num-of-days month) (cond [(= month 2) 28] [(or (= month 4) 例題3と同じ (= month 6) (= month 9) (= month 11)) 30] 例題3に [else 31])) 1行書き加える (easy-get-num-of-days 1) 2. DrScheme を使って,ステップ実行の様子を 確認しなさい (Step ボタン,Next ボタンを使用) • 理解しながら進むこと ☆ 次は,例題5に進んでください 45

46.

(easy-get-num-of-days 1) から 31 が得られる過程 (1/3) (easy-get-num-of-days 1) 最初の式 = (cond (cond [(= 1 2) 28] [(= month 2) 28] [(or (= 1 4) [(or (= month 4) (= month 6) (= 1 6) に month = 1 が代入される (= month 9) (= 1 9) (= month 11)) 30] (= 1 11)) 30] [else 31])) [else 31])) = (cond [false 28] [(or (= 1 4) (= 1 2) → false (= 1 6) (= 1 9) (= 1 11)) 30] [else 31])) = (cond [(or (= 1 4) (= 1 6) [false 0.040] → 消える (= 1 9) (= 1 11)) 30] コンピュータ内部での計算 46 [else 31]))

47.

(easy-get-num-of-days 1) から 31 が得られる過程 (1/3) (easy-get-num-of-days 1) = (cond [(= 1 2) 28] [(or (= 1 4) (= 1 6) (= 1 9) (= 1 11)) 30] [else 31])) = (cond [false 28] これは, [(or (= 1 (easy-get-num-of-days 4) (define month) (= 1 6) (cond (= 1 9) [(= 2) 28] (=month 1 11)) 30] (= month 4) [else[(or 31])) = (cond (= month 6) [(or (= 1(=4)month 9) (= 1(=6)month 11)) 30] (= 131])) 9) [else (= 1を11)) 30] の month 1 で置き換えたもの [else 31])) 47

48.

(easy-get-num-of-days 1) から 31 が得られる過程 (2/3) = (cond [(or false (= 1 6) (= 1 9) (= 1 11)) 30] [else 31])) = (cond [(or (= 1 9) (= 1 11)) 30] [else 31])) = (cond [(or false (= 1 11)) 30] [else 31])) = (cond [(or (= 1 11)) 30] [else 31])) = (cond [(or false) 30] [else 31])) (= 1 4) → false false → 消える (= 1 9) → false false → 消える (= 1 11) → false コンピュータ内部での計算 48

49.

(easy-get-num-of-days 1) から 31 が得られる過程 (3) = (cond (or false) → false [false 30] [else 31])) コンピュータ内部での計算 = 31 出力結果 49

50.

例題5.うるう年の判定 • 西暦年 year から,うるう年であるかを 求める関数 is-leap? を作り,実行する • うるう年の判定のために,比較演算と論理演算を組み合 わせる • 西暦年が 4, 100, 400 の倍数であるかを調べるために remainder を使う 例) 2001 → うるう年でない 2004 → うるう年である 50

51.

グレゴリオ暦でのうるう年 • うるう年とは: 2月が29日まである年 • うるう年は400年に97回で,1年の平均日数は 365.2422日 • うるう年の判定法 • 年数が4の倍数の年 → うるう年 • 但し, 100の倍数の年で400の倍数でない年 する) (例) → うるう年ではない (4の倍数なのだが例外と 2008年: うるう年(4の倍数) 2004年: うるう年(4の倍数) 2000年: うるう年(4の倍数) 1900年: うるう年ではない (100の倍数だが400の倍数でない) 1800年: うるう年ではない (100の倍数だが400の倍数でない)51

52.

うるう年の判定式 (or (= (remainder year 400) 0) (and (not (= (remainder year 100) 0)) (= (remainder year 4) 0))) 400の倍数である 100の倍数でない 4の倍数である かつ または 52

53.

「例題5.うるう年の判定」の手順 1. 次を「定義用ウインドウ」で,実行しなさい (define (is-leap? year) (cond [ (or (= (remainder year 400) 0) (and (not (= (remainder year 100) 0)) (= (remainder year 4) 0))) true] [else false])) 2. その後,次を「実行用ウインドウ」で実行しなさい (is-leap? 2004) (is-leap? 2005) ☆ 次は,例題6に進んでください 53

54.

まず,Scheme のプログラムを コンピュータに読み込ませている 54

55.

ここでは, (is-leap? 2004) と書いて,year の値を 2004 に設定しての実行 実行結果である「true」が 表示される 55

56.

今度は, (is-leap? 2005) と書いて,year の値を 2005 に設定しての実行 実行結果である「false」が 表示される 56

57.

入力と出力 2004 true is-leap? 入力 出力 出力は true あるいは false 値 57

58.

is-leap? 関数 「関数である」ことを 関数の名前 示すキーワード (define (is-leap? year) (cond [(or (= (remainder year 400) 0) (and (not (= (remainder year 100) 0)) (= (remainder year 4) 0))) true] [else false])) year の値から true 値を1つ受け取る(入力) あるいは false を求める(出力) 58

59.

うるう年の判定 1つの条件式 (define (is-leap? year) (cond [ (or (= (remainder year 400) 0) (and (not (= (remainder year 100) 0)) (= (remainder year 4) 0))) true] [else false])) 59

60.

例題6.ステップ実行 • 関数 is-leap? (例題5)について,実行結 果に至る過程を見る • (is-leap? 2004) から true に至る過程を見る • DrScheme の stepper を使用する (define (is-leap? year) (cond [ (or (= (remainder year 400) 0) (and (not (= (remainder year 100) 0)) (= (remainder year 4) 0))) true] [else false])) 60

61.

「例題6.ステップ実行」の手順 1. 次を「定義用ウインドウ」で,実行しなさい • • Intermediate Student で実行すること 入力した後に,Execute ボタンを押す (define (is-leap? year) (cond [ (or (= (remainder year 400) 0) (and (not (= (remainder year 100) 0)) (= (remainder year 4) 0))) true] [else false])) (is-leap? 2004) 例題5 と同じ 例題5に 1行書き加える 2. DrScheme を使って,ステップ実行の様子を 確認しなさい (Step ボタン,Next ボタンを使用) • 理解しながら進むこと ☆ 次は,例題7に進んでください 61

62.

(is-leap? 2004) から true が得られる過程 (1/3) 最初の式 (is-leap? 2004) = (cond (cond [(or (= (remainder year 400) 0) [(or (= (remainder 2004 400) 0) (and (not (= (remainder year 100) 0)) (= (remainder year 4) 0))) true] (and (not (= (remainder 2004 100) 0)) [else false]) (= (remainder 2004 4) 0))) true] に year = 2004 が代入される [else false])) = (cond [(or (= 4 0) (and (not (= (remainder 2004 100) 0)) (= (remainder 2004 4) 0))) true] (remainder 2004 400) → 4 [else false])) = (cond [(or false (and (not (= (remainder 2004 100) 0)) (= 4 0) → false (= (remainder 2004 4) 0))) true] [else false])) コンピュータ内部での計算 62

63.

(is-leap? 2004) から true が得られる過程 (1/3) (is-leap? 2004) = (cond [(or (= (remainder 2004 400) 0) (and (not (= (remainder 2004 100) 0)) (= (remainder 2004 4) 0))) true] [else false])) = (cond [(or (= 4 0) これは, (and (not (= (remainder 2004 100) 0)) (define (is-leap? year) 2004 4) 0))) true] (= (remainder (cond [else false])) = (cond [(or (= (remainder year 400) 0) [(or false(and (not (= (remainder year 100) 0)) 0)))0)) true] (and (not (= (= (remainder (remainder year 20044)100) [else (=false])) (remainder 2004 4) 0))) true] の year 2004 で置き換えたもの [elseを false])) 63

64.

(is-leap? 2004) から true が得られる過程 (2/3) = (cond [(or (and (not (= (remainder 2004 100) 0)) (or false 式) → (or 式) (= (remainder 2004 4) 0))) true] [else false])) = (cond (remainder 2004 100) → 4 [(or (and (not (= 4 0)) (= (remainder 2004 4) 0))) true] [else false])) = (cond [(or (and (not false) (= (remainder 2004 4) 0))) true] (= 4 0) → false [else false])) = (cond [(or (and true (= (remainder 2004 4) 0))) true] (not false) → true [else false])) コンピュータ内部での計算 64

65.

(is-leap? 2004) から true が得られる過程 (3/3) = (cond [(or (and (= (remainder 2004 4) 0))) true] (and true 式) → (and 式) [else false])) = (cond [(or (and (= 0 0))) true] (remainder 2004 4) → 0 [else false])) = (cond [(or (and true)) true] (= 0 0) → true [else false])) = (cond [(or true) true] (and true) → true [else false])) = (cond [true true] (or true) → true [else false])) コンピュータ内部での計算 65 = true 実行結果

66.

例題7.曜日を求める • ツエラーの公式 zellar を作り,実行する • ツエラーの公式とは: 西暦の年,月,日から曜日を 求める公式 • 年: 西暦の年 • 月: 3から14 • 計算された曜日は「数字」.次の意味になる. 0:日曜日 1:月曜日 2:火曜日 3:水曜日 4:木曜日 5:金曜日 6:土曜日 66

67.

ツエラーの公式での起点 • ツエラーの公式では,「1年の起点 を3月 とし、月は3月から14月まである」と考え ている • 1月,2月は,前年の13,14月と考えると いうこと • うるう年があるので,1年の起点を3月とす る方が計算が簡単 67

68.

ツエラーの公式 [(y+[y/4]+[y/400]-[y/100]+[(13m+8)/5]+d) mod 7] y: 年 m: 3月を起点とする月(3から14まで) 1月,2月は,前年の13,14月と考える d: 日 • この値が0なら日曜,1なら月曜・・・ • 「[]」とあるのは,小数点以下切り捨て • 「mod」 3 とあるのは剰余.例えば 2003 mod 4 は 68

69.

remainder • remainder の意味: • 割り算の余りを求める • (remainder x y) は,ツエラーの公式の x mod y に対応 69

70.

quotient • quotient の意味: • 整数の割り算の商を求める • (quotient x y) は, ツエラーの公式の [x / y] に対応 70

71.

ツエラーの公式のプログラム [(y+[y/4]+[y/400]-[y/100]+[(13m+8)/5]+d) mod 7] (define (zellar_f y m d) (remainder (+ y (quotient y 4) (quotient y 400) (- (quotient y 100)) (quotient (+ (* 13 m) 8) 5) d) 7)) ;; zellar : number number number -> number ;; to determine youbi (the day of the week) from year, month, and day. ;; The result is 0 ... 6 meaning 0 is Sunday, 1 Monday, and so on (define (zellar y m d) (cond [(or (= m 1) (= m 2)) (zellar_f (- y 1) (+ m 12) d)] [else (zellar_f y m d)])) 71

72.

4-3 課題 72

73.

課題1 • 次のような関数を作りなさい • cond を使うこと 50グラム以下なら → 120 75グラム以下なら → 140 100グラム以下なら → 160 150グラム以下なら → 200 73

74.

課題のヒント • ここにあるのは「間違い」の例です.同じ間 違いをしないこと 1.関数名の付け方の間違い (define (decide price w) ... 以下省略 ⇒ 「decice price」では無く, 「decide_price」のように1単語で書くこと 2.≦,≧をプログラム中に使うことはできない ⇒ 代わりに,<=, >= を使うこと 74

75.

課題2 • ある年 y のある月 m の日数を返す 関数 get-num-of-days を作成し,実 行結果を報告しなさい • easy-get-num-of-days(授業の例題 3)と, is-leap? (授業の例題5) を利用しなさい • うるう年の2月についても,正しい 日数を求めること 75

76.

課題3 次の値を求める関数 foo2 を書きなさい • • 「X mod 7」 は,X を 7 で割った時の余り(剰余). 例えば 2003 mod 4 は 3 である. • define と remainder を使いなさい. [(20x + 8) / 7] mod 10 76