この Notebook は,
テキスト「オープンソースソフトウェアによる情報リテラシー −第2版−」の
のプログラミング部分に相当する内容を,JavaScript のかわりに Julia を使って書いてみたものです。比較・対比しやすいように章番号を合わせています。
テキストとは関係なく,初めて Jupyter Notebook で Julia を利用する方にとっても参考になるかも知れません。 この Notebook では,プログラミング言語としての共通部分に焦点を絞って解説します。
では,はじめましょう。
なお,本稿執筆時点では,Julia の Jupyter kernel である IJulia を sysytem-wide にインストールすることはできないようです。利用者各自が最初に1回だけ,以下の手順を行う必要があります。
julia
を入力して対話型環境(REPL)に入る。julia>
のプロンプトに ]
を入力してパッケージマネージャモードに入る。add IJulia
と入力してしばらく成り行きを見守る。Ctrl-D
で終了)$ julia
_
_ _ _(_)_ | Documentation: https://docs.julialang.org
(_) | (_) (_) |
_ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
| | | | | | |/ _` | |
| | |_| | | | (_| | | Version 1.5.3 (2020-11-09)
_/ |\__'_|_|_|\__'_| | Official https://julialang.org/ release
|__/ |
julia> ]
(@v1.5) pkg> add IJulia
エンゲル係数とは,家計の消費支出に占める飲食費(食料費,食費)の割合(パーセント単位)です。
消費支出 100,000円,飲食費 40,000円の人のエンゲル係数を求める例。Julia では以下のような電卓的な使い方ですぐ答えが出ます。
本稿のように Jupyter Notebook 環境では,以下の1行を書いたあとに,Shift キーを押しながら Enter キー(または Return キー)を押して実行します。
40000/100000 * 100
ここからは,単に電卓的に使うだけではなく,応用・発展も見据えて以下のようなプログラム文を作成して実行することにします。
以下の例では,
s1
に消費支出である 100000
(円)という数値を代入し,s2
に飲食費である 40000
(円)という数値を代入し,x1
に代入し,x1
を表示させています。println()
は表示後,改行します。s1 = 100000
s2 = 40000
x1 = s2*100/s1
println(x1)
意に反して,プログラムがうまく動作しない場合があります。たとえば,上記の 3行目を以下のように書いた場合。
掛け算を示す演算子は *
であるところを誤って ×
と書くと,これらの記号は Julia では演算子として定義されていないのでエラーとなります。Jupyter Notebook では,以下のように誤りやその箇所を指摘してくれます。
s1 = 100000
s2 = 40000
x1 = s2 × 100 ÷ s1
println(x1)
別の種類の誤りもあります。たとえば,「100」を「1000」と入力した場合...
s1 = 100000
s2 = 40000
x1 = s2 * 1000 / s1
println(x1)
上記の例ではエラーの警告が出ませんが,答えは明らかに変です。(エンゲル係数の最大値は100だから。)
このような場合はコンピュータにとって誤りではなく,指示通りに計算し,その結果を表示します。 このようなプログラム作成者の不注意や勘違いによって生じるエラーには注意が必要です。
プログラムが正しく動作しない場合は,誤りの箇所を探し,修正して再度動作を確認します。正しく動作するようになるまで,プログラムを修正し,実行(Shift + Enter)します。この作業をデバグといいます。
上記の例の 1行目では,s1
という名前の変数に 100000
という
数値を代入しています。変数名はアルファベットで始まる英数字列にします。大文字と小文字は区別されます。
変数 ss
に文字列を代入する場合は,以下のように "
で囲みます。
ss="エンゲル係数"
println(ss)
掛け算を示す演算子は *
,割り算を示す演算子は /
。足し算は +
,引き算は -
です。
Julia では,文字列の連結演算は *
です。他の言語では +
を使うこともあるかと思いますが,Juliaでは連結演算は *
です。 以下の例を参照。
x0 = "エンゲル"
y0 = "係数"
z0 = x0 * y0
println(z0)
文字列と数値を直接連結することはできません。
s1 = 100000
s2 = 40000
x1 = s2*100/s1
z1 = "エンゲル係数は " * x1
println(z1)
そんなときは,string()
関数で数値を文字列に変換して連結します。
s1 = 100000
s2 = 40000
x1 = s2*100/s1
z1 = "エンゲル係数は " * string(x1)
println(z1)
println()
のところは,文字列にして連結しなくても,以下のようにも書くことができます。
println()
文は,カンマ (,
) で区切ることによって複数の項目(変数)を表示することができます。
println("エンゲル係数は ", x1)
もう一つの方法として,Julia では「文字列の補完」があります。$
の後に変数名を記述すると,文字列になります。以下の例を参照。
println("エンゲル係数は $x1")
2 + (50 - 5 * 6)/4
除算 /
は常に浮動小数点数を返します。 ÷
演算子は 整数除算を行い、(小数部を切り捨てた) 整数値を返します。剰余は、%
で求めます。
冪乗は ^
です。
17 / 3
17 ÷ 3
17 % 3
2^4
上記の例では,プログラムの中で消費支出や飲食費を決めていましたが,今度はプログラムを実行する人が入力できるようにしてみます。
Base.prompt()
関数は入力された「文字列」を返すので,数値として計算するために parse(Float64, )
で数値(浮動小数点数)に変換します。
s1 = Base.prompt("消費支出? ")
s2 = Base.prompt("飲食費? ")
s1 = parse(Float64, s1)
s2 = parse(Float64, s2)
x1 = s2 * 100 / s1
println("エンゲル係数は", x1)
(これまでの例では1回しか計算していませんが)よく使う計算を「関数」として定義する例です。
以下の例では,1行目から4行目でエンゲル係数を計算する関数 calc()
を定義し,8行目でその関数を呼び出しています。
#
から始まる行はコメント(実行に影響しない注釈)です。
function calc(s1, s2)
# 消費支出 s1 円と飲食費 s2 円からエンゲル係数を計算する。
return s2*100/s1
end
s1 = Base.prompt("消費支出? ")
s2 = Base.prompt("飲食費? ")
s1 = parse(Float64, s1)
s2 = parse(Float64, s2)
x1 = calc(s1, s2)
println("エンゲル係数は ", x1)
いったん定義された関数は,以下のように何回でも利用できます。
calc(120000, 53000)
消費支出を入力すると,エンゲル係数が 20 ~ 40 となる飲食費を表示するプログラムをつくりなさい。
Julia では,$\sin x, \cos x, \tan x$などの数学関数が組み込まれています。
# pi は円周率
pi, sin(pi/2), cos(pi/3), tan(pi/4)
また,切り捨て floor()
,切り上げ ceil()
,数値の丸めを行う round()
なども利用できます。
以下では,floor()
関数を使って小数点以下を切り捨てたエンゲル係数の値を表示させています。小数点以下を切り捨てた以上,答えは整数となるので,第1引数に Int
を指定して整数に変換します。
また,エンゲル係数を計算する部分はすでに関数 calc()
として定義していますが,プログラム全体を関数 engel()
として定義してしまいます。
function engel()
s1 = Base.prompt("消費支出? ")
s2 = Base.prompt("飲食費? ")
s1 = parse(Float64, s1)
s2 = parse(Float64, s2)
x1 = calc(s1, s2)
println("エンゲル係数は ", floor(Int, x1),
" です。(小数点以下切り捨て)")
end
engel()
小数点以下を切り上げたエンゲル係数の値を表示させるように上記のプログラムを変更しなさい。
Python の組み込み関数に round()
があります。数値を丸める関数ですが,いわゆる四捨五入とはちょっと違うようです。
以下の例からわかるように,小数点以下が 0.5
未満の場合と 0.5
を超える場合は四捨五入と同様の丸め方ですが,ちょうど 0.5
のときは,偶数に丸められていることがわかります。
これを偶数への丸めといい,端数が 0.5
より小さいなら切り捨て,端数が0.5
より大きいなら切り上げ,端数がちょうど 0.5
なら切り捨てと切り上げのうち結果が偶数となる方へ丸めます。
すでに利用した floor()
関数と同様に,round()
関数も数値を丸めたて整数として表示させたいときには以下のように第1引数に Int
を指定します。
round(Int, 12.49), round(Int, 12.50), round(Int, 12.51)
round(Int, 13.49), round(Int, 13.50), round(Int, 13.51)
端数がちょうど 0.5
のときに切り上げて 四捨五入 の動作をさせるには,round()
関数に以下のように RoundNearestTiesUp
オプションをつけます。
round(Int, 12.50), round(Int, 12.50, RoundNearestTiesUp)
function engel()
s1 = Base.prompt("消費支出? ")
s2 = Base.prompt("飲食費? ")
s1 = parse(Float64, s1)
s2 = parse(Float64, s2)
x1 = calc(s1, s2)
if x1 >= 80
println("エンゲル係数は ", round(Int, x1),
" です。飲食費を使いすぎです。")
else
println("エンゲル係数は ", round(Int, x1), " です。")
end
end
engel()
engel()
条件分岐の if
文の書式は以下のとおりです。
if 条件式1
条件式1 が満たされた場合に実行する文
elseif 条件式2
条件式2 が満たされた場合に実行する文
else
それ以外の場合に実行する文
end
上記の条件分岐を,エンゲル係数が
と表示させるように変更しなさい。
以下の例では,1行目で代入された消費支出に対してエンゲル係数を計算します。
1回だけ計算して表示するのではなく,2行目の飲食費の初期値(ここでは 40000
円)から,5行目の条件式(ここでは 80000
円以下)が成り立つ場合に,8行目にあるように 5000
円ずつ増やしながらエンゲル係数を表示します。
s1 = 100000
s2 = 40000
println("消費支出 ",s1,"円に対するエンゲル係数の値")
while s2 <= 80000
x1 = calc(s1, s2)
println(" 飲食費 ", s2, "円の場合: ", x1)
s2 = s2 + 5000
end
while
文の書式は以下の通りです。
while 条件式
条件式が成り立つ場合に実行する式
end
同様の繰り返し処理を for
文を使って行うこともできます。
s1 = 100000
println("消費支出 ",s1,"円に対するエンゲル係数の値")
for s2 = 40000:5000:80000
x1 = calc(s1, s2)
println(" 飲食費 ", s2, "円の場合: ", x1)
s2 = s2 + 5000
end
for
文の書式は以下のとおりです。増分を省略すると 1
とみなします。
for i = 開始値:増分:終端値
i が開始値以上,終端値以下の場合に実行される文
end
=
の部分を in
としてもよいようです。
for i in 1:5
print(i, " ")
end
以下の値を求めるプログラムを作成せよ。
$$\sum_{n = 1}^{10} n^2$$