<style>
/* basic design */
.reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6,
.reveal section, .reveal table, .reveal li, .reveal blockquote, .reveal th, .reveal td, .reveal p {
font-family: 'Meiryo UI', 'Source Sans Pro', Helvetica, sans-serif, 'Helvetica Neue', 'Helvetica', 'Arial', 'Hiragino Sans', 'ヒラギノ角ゴシック', YuGothic, 'Yu Gothic';
text-align: left;
line-height: 1.6;
letter-spacing: normal;
text-shadow: none;
word-wrap: break-word;
color: #444;
}
.reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6 {font-weight: bold;}
.reveal h1, .reveal h2, .reveal h3 {color: #00a474;}
.reveal th {background: #DDD;}
.reveal section img {background:none; border:none; box-shadow:none; max-width: 95%; max-height: 95%;}
.reveal blockquote {width: 90%; padding: 0.5vw 3.0vw;}
.reveal table {margin: 1.0vw auto;}
.reveal code {line-height: 1.2;}
.reveal p, .reveal li {padding: 0vw; margin: 0vw;}
.reveal .box {margin: -0.5vw 1.5vw 2.0vw -1.5vw; padding: 0.5vw 1.5vw 0.5vw 1.5vw; background: #e4ffe5; border-radius: 1.5vw;}
/* table design */
.reveal table {background: #f5f5f5;}
.reveal th {background: #444; color: #fff;}
.reveal td {position: relative; transition: all 300ms;}
.reveal tbody:hover td { color: transparent; text-shadow: 0 0 3px #aaa;}
.reveal tbody:hover tr:hover td {color: #444; text-shadow: 0 1px 0 #fff;}
/* blockquote design */
.reveal blockquote {
width: 90%;
padding: 0.5vw 0 0.5vw 6.0vw;
font-style: italic;
background: #ddffff;
}
.reveal blockquote:before{
position: absolute;
top: 0.1vw;
left: 1vw;
content: "\f10d";
font-family: FontAwesome;
color: #00a474;
font-size: 3.0vw;
}
/* font size */
.reveal h1 {font-size: 5.0vw;}
.reveal h2 {font-size: 4.0vw;}
.reveal h3 {font-size: 2.8vw;}
.reveal h4 {font-size: 2.6vw;}
.reveal h5 {font-size: 2.4vw;}
.reveal h6 {font-size: 2.2vw;}
.reveal section, .reveal table, .reveal li, .reveal blockquote, .reveal th, .reveal td, .reveal p {font-size: 2.2vw;}
.reveal code {font-size: 1.6vw;}
/* new color */
.red {color: #EE6557;}
.blue {color: #16A6B6;}
/* split slide */
#right {left: -18.33%; text-align: left; float: left; width: 50%; z-index: -10;}
#left {left: 31.25%; text-align: left; float: left; width: 50%; z-index: -10;}
</style>
<style>
/* backgroud design */
.reveal {
background-color:/*背景色*/
#f8f8ff;
}
.reveal h1 {padding: 3.0vw 0vw;}
@media screen and (max-width: 1024px) {
.reveal h2 {margin: -2.0vw 0 0 0; padding: 0.0vw 0vw 3.0vw 2.0vw; }
}
@media screen and (min-width: 1025px) and (max-width: 1920px) {
.reveal h2 {margin: -1.5vw 0 0 0; padding: 0.0vw 0vw 3.0vw 2.0vw; }
}
@media screen and (min-width: 1921px) and (max-width: 100000px) {
.reveal h2 {margin: -1.0vw 0 0 0; padding: 0.0vw 0vw 3.0vw 2.0vw; }
}
</style>
<style>
/* specific design */
.reveal h2 {
padding: 0 1.5vw;
margin: 0.0vw 0 2.0vw -2.0vw;
border-left: solid 1.2vw #00a474;
border-bottom: solid 0.8vw #9e9e9e;
}
</style>
---
title: 第5章
tags: presentation
2021 10/05
杉山俊
---
# 条件分岐の構文
場合分けを行う場合if文をつかう。構文は
**if 条件 then 式1 else 式2**
if文を使うときは、型に関して2つの要件を満たさなくてはいけない
**「条件」はbool型でなくてはならない。
ふたつの「式」は同じ型を持たなくてはならない**
if文全体の型は式の型として扱われる
---
例題
```ocaml=
if true then 1 else 2;;
- : int = 1
if 3 + 4 < 5 then 1 else 2;;
- : int = 2
```
条件をbool型以外で書いた時のエラー文
```ocaml=
if 1 then 2 else 3;;
Error: This expression has type int but an expression was expected of type
bool
because it is in the condition of an if-statement
#
```
式に違う方を入れたときのエラー文
```ocaml=
if true then 1 else "2";;
Error: This expression has type string but an expression was expected of type
int
```
---
**式の中にif分を組み込む**
```ocaml=
(*目的 週に30時間働いた人は優遇時給980円 30未満は950円の時給を与える*)
(*基本給*)
let kihonkyu = 100;;
(*時給*)
let jikyu = 950;;
(*優遇時給*)
let yugu_jikyu = 980;;
let kyuyo x =
if x < 30 then kihonkyu + x * jikyu
else kihonkyu + x * yugu_jikyu;;
```
30時間未満 基本給+働いた時間* 通常自給
30時間以上 基本給+働いた時間* 優遇自給
このとき給与の計算方法が誰に対してもいつでも適用されるなら
kihonkyu + x の部分は同じものなので省略できる。すると
```ocaml=
let kyuyo x =
kihonkyu + x * (if x < 30 then jikyu else yugu_jikyu);;
```
と書くことができる。このときif文は式であるjikyu、yugu_jikyuと同じint型として扱われている。
---
# 条件分岐のデザインレシピ
1. どのような場合分けがあるか考える
すべての場合に対して例を作る。(境目などの微妙な場合もあるとよい)
2. 場合分けの条件を特定し、必要な場合分けを行うif文を作る。(この段階では式の部分には方にあった適当な値を入れる。)
3. プログラムが動作するか確認する。(この時点では本体の作成をしていないので基本的にfalseになる)
4. プログラムの大枠が完成したらthen else部分を作成していきtestプログラムを1つの場合につき1つのtestは実行するようにする。
---
変数を受け取り、その絶対値を返す関数abs_valueをデザインレシピに従って作る。
この関数の目的は「受け取った実数の絶対値を計算する」なので型はfloat -> floatとなる。
```ocaml=
(*目的:受け取った実数xの絶対値を計算する*)
(*abs_value : float -> float*)
let abs_value x = 0.0;;
```
絶対値を返す関数なので正の数だったらそのまま受け取ったものを返し、負の数だったらマイナスを取った値を返すテストプログラムを作る。
```ocaml=
(*テスト*)
let test1 = abs_value 2.8 = 2.8;;
let test2 = abs_value (-2.8) = 2.8;;
```
微妙なケース0もつくっておく
```ocaml=
let test3 = abs_value 0.0 = 0.0;;
```
---
プログラムが動作するかテストする
```ocaml=
#use "abs_value.ml";;
val abs_value : 'a -> float = <fan>
val test1 : bool = false
val test2 : bool = false
val test3 : bool = true
```
test3は適当な値とたまたま一緒だったためtrueになったが
基本的にfalseになる。
---
テストできることが分かったので本体の作成をする。
どのような場合分けを必要か考え、それに従って場合分けを行うif文を作成する。
abs_value の場合は引数xが正か負かで場合分けをする。
```ocaml=
(*目的:受け取った実数xの絶対値を計算する*)
(*abs_value : float -> float*)
let abs_value =
if x > 0.0 then 0.0
else 0.0;;
```
適当な数値で場合分けが動作するか確認する。
```ocaml=
#use "abs_value.ml";;
val abs_value : float -> float = <fan>
val test1 : bool = false
val test2 : bool = false
val test3 : bool = true
```
---
本体を1つずつ作成していく。
```ocaml=
(*目的:受け取った実数xの絶対値を計算する*)
(*abs_value : float -> float*)
let abs_value x =
if x > 0.0 then x
else 0.0;;
```
この時点でのテストプログラムを実行
```ocaml=
#use "abs_value.ml";;
val abs_value : float -> float = <fan>
val test1 : bool = true
val test2 : bool = false
val test3 : bool = true
```
---
想定通りに動いたのでtest1がtrueとなる。最後にxが負の場合を考える。この場合は符号を反転して返せばよいので
```ocaml=
(*目的:受け取った実数xの絶対値を計算する*)
(*abs_value : float -> float*)
let abs_value x =
if x > 0.0 then x
else -. x ;;
```
となる。(-. x は 0.0 -. xと同じ)
テストプログラムを動かすと
```ocaml=
#use "abs_value.ml";;
val abs_value : float -> float = <fan>
val test1 : bool = true
val test2 : bool = true
val test3 : bool = true
```
となりすべてのテストがtrueを返すようになる。
---
次は現在の気温tを整数で受け取り、その値が15以上25以下だったら「快適」、それ以外だったら「普通」という文字列を返す関数kionを作る。
関数の目的は「現在の気温から快適度を表す文字列を計算する」とする。
型は int -> stringとなるのでヘッダは次のようになる。
```ocaml=
(*目的 : 現在の気温tから快適度を表す文字列を計算する*)
(*kion : int -> string*)
let kion t = "";;
```
次に例を作る。気温が15度と25度で場合が分かれるので境界の場合も含め以下の5通りの例を作る。
```ocaml=
let test1 = kion 7 = "普通"
let test2 = kion 15 = "快適"
let test3 = kion 20 = "快適"
let test4 = kion 25 = "快適"
let test5 = kion 28 = "普通"
```
現時点ではkionに文字を入れてないのですべてfalseを返す。
次に場合分けを考える。1つ目の方法は
①15度未満 ②15度以上25度未満 ③25度以上
の3通りで考えると
```ocaml=
(*目的 : 現在の気温tから快適度を表す文字列を計算する*)
(*kion : int -> string*)
let kion t =
if t < 15 then ""
else if t <= 25 then ""
else "";;
```
となりあとは順に作ると
```ocaml=
(*目的 : 現在の気温tから快適度を表す文字列を計算する*)
(*kion : int -> string*)
let kion t =
if t < 15 then "普通"
else if t <= 25 then "快適"
else "普通";;
let test1 = kion 7 = "普通"
let test2 = kion 15 = "快適"
let test3 = kion 20 = "快適"
let test4 = kion 25 = "快適"
let test5 = kion 28 = "普通"
```
となる。
---
1つめは「15度以上25度以下だったら快適」という記述に完全に対応するものではないので、2つ目は①15度以上25度以下②それ以外 の2通りで場合分けする。
```ocaml=
(*目的 : 現在の気温tから快適度を表す文字列を計算する*)
(*kion : int -> string*)
let kion t =
if 15 <= t && t <= 25 then "快適"
else "普通"
```
このように条件の部分には一つの比較ではなく複数の複雑な比較の条件を書くことができる。今回の場合ではそこまで複雑ではないためより条件が増えたとき複雑になり見通しが悪くなる。それを解決するには条件部分の関数を作るというのがある。kionを例に作ってみる。
---
tが15度以上25度以下であるかをチェックする関数kaitekiを定義する。この関数は「受け取った値が15度以上25度以下であるかを判定する」ものなので返す型はbool型となる。関数の方はint -> boolとなる。
```ocaml=
(*目的:現在の気温tが15度以上25度以下であるかを判定する*)
(*kaiteki : int -> bool*)
let kaiteki t = false;;
```
テストプログラムを作る
```ocaml=
let test1 = kaiteki 7 = false;;
let test2 = kaiteki 15 = true;;
let test3 = kaiteki 20 = true;;
let test4 = kaiteki 25 = true;;
let test5 = kaiteki 28 = false;;
```
となる。
テストプログラムができたら本体作成
```ocaml=
(*目的:現在の気温tが15度以上25度以下であるかを判定する*)
(*kaiteki : int -> bool*)
let kaiteki t =
15 <= t && t <= 25;;
```
これでテストプログラムはすべてtrueになる。
これをつかってkionを書き換える。
```ocaml=
(*目的 : 現在の気温tから快適度を表す文字列を計算する*)
(*kion : int -> string*)
let kion t =
if kaiteki t then "快適"
else "普通";;
```
となり見やすくなる。ここでもテストプログラムを動かし正常に動くことを確かめる。
# 条件分岐の実行方法
例
```ocaml=
let kyuyo x =
kihonkyu + x * (if x < 30 then jikyu else yugu_jikyu)
```
kyuyo 31 のとき
①kihonkyu + **31** * (if **31** < 30 then jikyu else yugu_jikyu)
②**100** + 31 * (if 31 < 30 then jikyu else yugu_jikyu)
③100 + 31 * (if **false** then jikyu else yugu_jikyu)
④100 + 31 * **yugu_jikyu**
の順で実行される。
---
**5.2**
```ocaml=
(*受け取った時間xを午前か午後か判定する*)
(* jikan : int -> string *)
let jikan x y =
if x < 12 then "午前"
else "午後";;
(*let test1 = jikan 9 0 = "午前" ;;
let test2 = jikan 12 11 = "午後" ;;
let test3 = jikan 15 30 = "午後";;*)
(*デザインレシピ1
let jikan x y = "午前" ;;
# #use "5-2.ml";;
val jikan : int -> 'a -> string = <fun>
val test1 : bool = true
val test2 : bool = false
val test3 : bool = false*)
(*デザインレシピ2
let jikan x y =
if x < 12 then "午前"
else "午前";;
#use "5-2.ml";;
val jikan : 'a -> 'b -> string = <fun>
val test1 : bool = true
val test2 : bool = false
val test3 : bool = false
*)
(*デザインレシピ3
let jikan x y =
if x < 12 then "午前"
else "午後";;
# #use "5-2.ml";;
val jikan : int -> 'a -> string = <fun>
val test1 : bool = true
val test2 : bool = true
val test3 : bool = true*)
```
---
**5.3**
```ocaml=
(*受け取った月xと日付yで星座を判別する*)
(* seiza : int -> int -> int -> string*)
let seiza x y =
if x = 1 && y < 20 then "山羊座"
else if x = 1 && y < 32 then "水瓶座"
else if x = 2 && y <= 18 then "水瓶座"
else if x = 2 && y > 18 then "魚座"
else if x = 3 && y <= 20 then "魚座"
else if x = 3 && y > 20 then "牡羊座"
else if x = 4 && y <= 19 then "牡羊座"
else if x = 4 && y > 19 then "牡牛座"
else if x = 5 && y <= 20 then "牡牛座"
else if x = 5 && y > 20 then "双子座"
else if x = 6 && y <= 21 then "双子座"
else if x = 6 && y > 21 then "蟹座"
else if x = 7 && y <= 22 then "蟹座"
else if x = 7 && y > 22 then "獅子座"
else if x = 8 && y <= 22 then "獅子座"
else if x = 8 && y > 22 then "乙女座"
else if x = 9 && y <= 22 then "乙女座"
else if x = 9 && y > 22 then "天秤座"
else if x = 10 && y <= 23 then "天秤座"
else if x = 10 && y > 23 then "蠍座"
else if x = 11 && y <= 22 then "蠍座"
else if x = 11 && y > 22 then "射手座"
else if x = 12 && y <= 21 then "射手座"
else if x = 12 && y > 21 then "魚座"
else "該当日付なし" ;;
let test1 = seiza 1 19 = "山羊座";;
let test2 = seiza 2 17 = "水瓶座";;
let test3 = seiza 2 20 = "魚座";;
```
---
**4.4 4.5 4.6**
```ocaml=
(*4-4*)
(*目的 入力された3つの値a b cを判別式にに代入する*)
(*hanbetsushiki : int -> int -> int -> int*)
let hanbetsushiki a b c = b * b - 4 * a * c ;;
let test1 = hanbetsushiki 1 2 3 = -8 ;;
let test2 = hanbetsushiki 2 2 2 = -12;;
let test3 = hanbetsushiki 1 10 9 = 64;;
(*4-5*)
(*目的 入力された3つの値a b cを使って解の個数を調べる*)
(*kai_no_kosuu int -> int -> int -> string*)
let kai_no_kosuu a b c =
if hanbetsushiki a b c > 0 then "2個"
else if hanbetsushiki a b c = 0 then "1個"
else "0個";;
let test4 = kai_no_kosuu 1 4 4 = "1個";;
let test5 =kai_no_kosuu 1 2 3 = "0個";;
let test6 = kai_no_kosuu 1 10 9 = "2個";;
(*4-6*)
(*目的 入力された3つの値a b c を使って虚数解をもつか調べる*)
(*kyosuukai int -> int -> int-> -> string*)
let kyosuukai a b c =
if hanbetsushiki a b c < 0 then "虚数解を持つ"
else "虚数解を持たない";;
let test7 = kyosuukai 1 4 4 = "虚数解を持たない";;
let test8 = kyosuukai 1 2 3 = "虚数解を持つ";;
let test9 = kyosuukai 1 10 9 = "虚数解を持たない";;
```
---
**5.7**
```ocaml=
(*二つの値を入力しbmiから得られた値をもとに体型を返す*)
(*taikei float - > float -> string*)
(*bmi計算*)
let bmi x y = y /. (x ** 2.0 );;
let taikei x y =
if bmi x y < 18.5 then "やせ"
else if bmi x y >=18.5 && bmi x y < 25.0 then "標準"
else if bmi x y >= 25.0 && bmi x y < 30.0 then "肥満"
else "高度肥満";;
let test1 = taikei 1.5 50.0 = "標準";;
let test2 = taikei 1.7 45.0 = "やせ";;
let test3 = taikei 1.5 70.0 = "高度肥満";;
let test4 = taikei 1.7 75.0 = "肥満";;
```
{"metaMigratedAt":"2023-06-16T11:23:18.017Z","metaMigratedFrom":"YAML","title":"5章","breaks":true,"slideOptions":"{\"theme\":\"white\",\"slideNumber\":\"c/t\",\"center\":false,\"transition\":\"none\",\"keyboard\":true,\"width\":\"93%\",\"height\":\"100%\"}","contributors":"[{\"id\":\"f70b5781-e87b-4bd3-b58a-3475941e5702\",\"add\":12966,\"del\":271}]"}