第3回:▼ 連続な曲線を描く

■ Jupyter notebook によるテキストの入力

Markdownセルと Markdown 記法

Jupyter notebook のセルには,複数の種類(Cell type)がある.

既定のセルの Cell type は,Code である. プログラム片を入力して,SHIFT キーと ENTER キーを同時に押して実行すると, 出力セルに実行結果が表示される.

Cell type を Markdown に変更すると, Markdown 記式によるテキストを入力できる.

Markdown 記式でテキストを入力し, SHIFT+ENTERを押して実行すると, Markdown記式で整形された文書が表示される.

Markdown Cells

Markdown記法では,段落の区切りは空行である. 空行をはさまない行替えは,前の行に続けて,同じ段落に配置される.

文字列の飾り記法は省略する(たくさん使用しない方がよい).

URLリンク

URLリンクを書くには,次のように記述する.→ [ 表示名 ]( URL )

[Julia 1.9 Documentation](https://docs.julialang.org/en/v1.10/)

Julia 1.9 Documentation

数式

Markdown記法では,数式を挿入することができる. ダラー記号 $ 1つで囲まれた数式は行内数式(inline math), ダラー記号 $ 2つで囲まれた数式は別行立て数式(display math)である. 数式そのものは LaTeX 記法で記述する. いくつか例を示す.

  • 数式内の文字は変数とみなされ,斜体で表される. $x+1$$x+1$
  • 上付き $x^{2}$$x^{2}$
  • 下付き $x_{3}$$x_{3}$
  • 分数 $\dfrac{a}{b}$$\dfrac{a}{b}$
  • 関数 $f(x) = x^{2}+1$$f(x) = x^{2}+1$
  • 三角関数 $\sin{x}, \tan{x}$$\sin{x}, \tan{x}$
  • 指数対数関数 $\exp{x}, \log{x}$$\exp{x}, \log{x}$
  • テキスト内の直立体(roman style) $a\;\mathrm{over}\;b$$a\;\mathrm{over}\;b$
  • 総和 $\sum_{i=0}^{m}i$$\sum_{i=0}^{m}i$
  • 総和を「行立て」する $$\sum_{i=0}^{m}i$$

\[\sum_{i=0}^{m}i\]

  • 積分 $\int_{0}^{1}x dx$$\int_{0}^{1}x dx$
  • 積分を「行立て」する $$\int_{0}^{1}x dx$$

\[\int_{0}^{1} x dx\]

  • カッコのペア
    • $\left( \dfrac{1}{2} \right)$

\[\left( \dfrac{1}{2} \right)\]

  • $\left\{\left( \dfrac{1}{2} \right)\right\}$

\[\left\{\left( \dfrac{1}{2} \right)\right\}\]

  • $\left[\left\{\left( \dfrac{1}{2} \right)\right\}\right]$

\[\left[\left\{\left( \dfrac{1}{2} \right)\right\}\right]\]

▼ 鉛直上投げ自由落下運動を描く

(力学の問題)

鉛直上向きに投げられた球が,重力のみを感じて自由落下するとする. 時刻 $t=0$において,高さ $y=0$, 鉛直上向きの速度 $v_0$ とすると, 時刻 $t$における,高さ $y$と 鉛直上向きの速度 $v$ は,以下のように表される.

\[\begin{aligned} v & = v_0 - gt, \\ y & = v_0 t - \dfrac{1}{2}gt^2 \end{aligned}\]

各時刻の速度を描く. 長さの単位としてメートル m , 時間の単位として秒 s を(組立て単位を含めて)一貫して用いる.

重力加速度 $g = 9.8\;\mathrm{m/s^2}$

初速度を $v_0 = 10\;\mathrm{m/s}$ としよう.

各時刻における速度を描く.

using Plots
#gr() #pythonplot()

plot(framestyle=:axes)
v0 = 10 # m/s
g = 9.8 # m/s^2

ts = 0:0.1:3 # s
vs = v0 .- g * ts
plot!(ts, vs, lc=:blue, xlabel="time / s", ylabel="v / m s^-1")

各時刻における高さを描く.

# 続けて
ys = v0 * ts .- g * ts .^ 2 / 2
plot(ts, ys, lc=:red, xlabel="time / s", ylabel="y / m")

この後の章の ▲ 鉛直上投げ自由落下運動を描く・上下2枚のサブプロット では, 速度-時刻,高さ-時刻の二つのプロットを一つの画像にまとめる.さらに, ▲ 鉛直上投げ自由落下運動を描く・ダブルYプロット では,時刻を共通としたダブルYグラフを作成する.

▲ 練習:鉛直上投げ自由落下運動

初速度 v0 を増減して描いてみよ.

▲ 練習:斜めに飛ばした球の軌跡

(力学の問題)

鉛直上向きに対して 角度 $b$をつけて投げた球が,重力のみを感じて運動するとき,その球の軌跡を描け.

最初は $b = 15^{\circ}$として描け.

次に,初速度$v0$を変えた場合を,1つのプロットに示せ. また,角度$b$を変えた場合を,1つのプロットに示せ.

▼ 定義域・値域

関数 $y=f(x)$ の定義域(domain)とは, 独立変数(independent variable)$x$ の取りうる値からなる集合である. ちなみに,従属変数(dependent variable) $y$ が取りうる値からなる集合を,値域(range)という

本章では, 定義域が実数全体,あるいは,正の数の集合である関数について, プロットを描いてみる.

▶ 定数 pi

定数 pi は円周率である.

julia> piπ = 3.1415926535897...

プロット既定値

using Plots
#gr() #pythonplot()
Plots.reset_defaults()
default(
   size=(720,480),  # <= 全体の寸法を大きくする
   lims=:auto, aspect_ratio=:auto,
   label="",
   xlabel="x", ylabel="y")

▼ 正弦関数・余弦関数を描く

関数数式ラジアン単位角度単位$pi$単位
正弦$\sin{x}$sin(x)sind(x)sinpi(x)
余弦$\cos{x}$cos(x)cosd(x)cospi(x)

ラジアン単位

引数がラジアン単位の正弦,余弦 sin , cos

julia> sin(pi / 6)0.49999999999999994
julia> cos(pi / 6)0.8660254037844387

cos.()sin.() のように,関数名の直後にピリオド . を入れると, ベクトルや範囲を引数にとり,計算結果をベクトルで返す.

julia> xs = [pi / 4, pi / 6, pi / 2];
julia> sin.(xs)3-element Vector{Float64}: 0.7071067811865475 0.49999999999999994 1.0
julia> cos.(xs)3-element Vector{Float64}: 0.7071067811865476 0.8660254037844387 6.123233995736766e-17

範囲型の引数を与えて,プロットを描く.

using Plots
#gr() #pythonplot()
xs = -2pi:pi/360:2pi
plot(xlabel="radian", ylims=(-1.2,1.2))
plot!(xs, cos.(xs), label = "cos")
plot!(xs, sin.(xs), label = "sin")
vline!([0], lc=:black, lw=0.5)

円周率単位

引数が円周率単位の正弦,余弦 sinpi , cospi

using Plots
#gr() #pythonplot()
xs = -2:1/360:2
plot(xlabel="pi", ylims=(-1.2,1.2))
plot!(xs, cospi.(xs), label = "cospi")
plot!(xs, sinpi.(xs), label = "sinpi")
vline!([0], lc=:black, lw=0.5)

角度単位

引数が角度単位の正弦,余弦 sind , cosd

using Plots
#gr() #pythonplot()
plot(
   xlabel="degree", ylims=(-1.2,1.2))
xs = -360:1:360
plot!(xs, cosd.(xs), label = "cosd")
plot!(xs, sind.(xs), label = "sind")
plot!(xticks=-360:90:360) # <= 横軸目盛の設定
vline!([0], lc=:black, lw=0.5)

ラジアンと角度との相互変換

julia> # rad2deg
       rad2deg(pi / 4)45.0
julia> rad2deg(pi / 2)90.0
julia> rad2deg(pi)180.0
julia> rad2deg(-pi / 4) # deg2rad-45.0
julia> deg2rad(45)0.7853981633974483
julia> deg2rad(90)1.5707963267948966
julia> deg2rad(180)3.141592653589793
julia> deg2rad(-45)-0.7853981633974483

▼ 楕円を描く

楕円を陰関数で表示すると

\[\left(\dfrac{x}{a}\right)^2+\left(\dfrac{y}{b}\right)^2 = 1\]

楕円を媒介変数表示(パラメータ曲線)すると

\[\begin{aligned} x & = a \cos \theta \\ y & = b \sin \theta \end{aligned}\]

媒介変数表示を用いて,楕円上の各点の座標を計算する.

アスペクト比を等しくして,正しい図形を表示しよう.

using Plots
#gr() #pythonplot()
plot(aspect_ratio=:equal, legend=false)
ts = 0:pi/18:2pi
xs = cos.(ts)
ys = sin.(ts)
plot!(xs, ys, label="circle")
xs2 = 2 * cos.(ts)
plot!(xs2, ys, label="ellipse")

▼ アルキメデスの渦を描く

平面座標上の点 $(x,y)$は, 極座標 $(r, \theta)$ を用いても表示できる. 平面座標 $(x, y)$と極座標 $(r, \theta)$ との対応は

\[\begin{aligned} x & = r \cos \theta, \\ y & = r \sin \theta \end{aligned}\]

である.

次の関係で結ばれた曲線を,アルキメデスの渦という.

\[r = \theta\]

これを描いてみよう.

using Plots
#gr() #pythonplot()
plot(aspect_ratio=:equal, legend=false)
ts = 0:pi/180:2pi
xs = ts .* cos.(ts)
ys = ts .* sin.(ts)
plot!(xs,ys)

▲ 練習

上では $\theta \ge 0$ の範囲で,曲線を描いた. パラメータ $\theta < 0$ の範囲まで含めたら, どのような曲線になるか,予測せよ. プログラムを書き実行し,確かめてみよ. 予測と合っていたか?

▼ 花曲線を描く

整数 $n$ に対して,以下の式で表される曲線を,花曲線(flower curve)という.

\[r = \cos(n \theta)\]

次のプログラムは,$n = 3$ の花曲線を描く.

using Plots
#gr() #pythonplot()
plot(aspect_ratio=:equal, legend=false)
n = 3
ts = 0:pi/180:2pi
rs = cos.(n * ts)
xs = rs .* cos.(ts)
ys = rs .* sin.(ts)
plot!(xs, ys)

整数 $n$ を変えると,色々な花曲線が得られる.

▲ 練習

上の式の代わりに

\[r = \sin(n \theta)\]

としたら,どのような曲線になるか? 予想した上で,プログラムを書き実行し,確かめてみよ. 予想と一致していたか?

▼ 指数関数を描く

数式Julia
$a > 0$$a^{x}$a^x
$2$$2^{x}$exp2(x)
$e$$e^{x}$, $\exp{x}$exp(x)
$10$$10^{x}$exp10(x)

正の数 $a > 0$ を底(exponent)とする指数関数(exponential function)

\[y = a^x\]

$a = 2$ の場合.

using Plots
#gr() #pythonplot()
plot(legend=false)

xs = -3:0.01:3
plot!(xs, 2.0 .^ xs)

底を $2, 3, 4. 5$ と増やす.$x > 0$ の範囲のみ描く.

using Plots
#gr() #pythonplot()
plot(xlims=(0,3))

xs = -3:0.01:3
plot!(xs, 2.0 .^ xs, label = "a=" * string(2))
plot!(xs, 3.0 .^ xs, label = "a=" * string(3))
plot!(xs, 4.0 .^ xs, label = "a=" * string(4))
plot!(xs, 5.0 .^ xs, label = "a=" * string(5))
plot!(xs, 6.0 .^ xs, label = "a=" * string(6))

▲ 練習:指数関数:繰り返しで底を変える

上のプログラムを,for 文を用いた繰り返しとして書き直してみよ. すなわち,plt.plot() 文を1つにしてみよ.

参考→ for

▶ 自然対数の底

定数 は,自然対数の底である.

julia> ℯℯ = 2.7182818284590...
Note

e とは異なる文字である. 「ℯ」は,バックスラッシュ \ に続けて euler と入力してから,TABキーを押すことによって入力できる.

定数 Base.MathConstants.e も,自然対数の底である.

julia> Base.MathConstants.eℯ = 2.7182818284590...

▶ 軸のスケールを変える

$x$ 軸,$y$ 軸のスケールを指定するには, キーワード引数 xscale , yscale を用いる. 何も指定しない場合(既定値)は,線形 :linear である. 引数に :log を指定すると,$10$ の対数で,その軸を描く.

$y$ 軸だけ対数スケール yscale=:log10 に指定したプロットが,よく見る片対数プロットである.

using Plots
#gr() #pythonplot()
plot(yscale=:log10)  # <=

xs = -4:0.01:4
for a in [2.0, ℯ, 3.0, 4.0, 5.0, 6.0]
   plot!(xs, a .^ xs, label = "a=" * string(a))
end
xlims!(-1, 3)
ylims!(1e-1, 1e3)

すべての底について,指数関数が $a^{0} = 1 = 10^{0}$ で交わることを観察するために補助線を引こう.

以下の文を追加する.

# 上に続けて
vline!([0], color = :black, lw = 0.5)
hline!([1], color = :black, lw = 0.5)

▶ 関数 exp, exp2, exp10

$2, e, 10$ については,exp で始まる関数が定義されている.

  • exp2 : 底が $2$ の指数関数
  • exp : 自然対数(底は,自然対数の底 $e$
  • exp10 : 底が $10$ の指数関数
using Plots
#gr() #pythonplot()
plot(yscale=:log10)

xs = -4:0.01:4
plot!(xs, exp2.(xs), label = "exp2")
plot!(xs, exp.(xs), label = "exp")
plot!(xs, exp10.(xs), label = "exp10")
xlims!(-1, 3)
ylims!(1e-1, 1e3)
vline!([0], color = :black, lw = 0.5)
hline!([1], color = :black, lw = 0.5)

関数も名前であり,名前をつけること(=変数に代入すること)ができる. 関数のリストを作って for 文で繰り返してみよう. 関数名を string 関数に与えると,関数名の文字列を返す.

using Plots
#gr() #pythonplot()
plot(yscale=:log10)

xs = -4:0.01:4
for f in [exp2, exp, exp10]
   plot!(xs, f.(xs), label = string(f))
end
xlims!(-1, 3)
ylims!(1e-1, 1e3)
vline!([0], color = :black, lw = 0.5)
hline!([1], color = :black, lw = 0.5)

▼ 冪乗根を描く

数式Julia
$2$$\sqrt{x}$sqrt(x)
$3$$\sqrt[3]{x}$cbrt(x)
$n > 0$$\sqrt[n]{x}$, $x^{\frac{1}{n}}$x^(1/n)

▼ 平方根を描く

二乗すると $x$ になる数を,$x$ の平方根(square root of $x$ )という. 関数 sqrt(x)x の平方根を求める関数である.

julia> sqrt(0)0.0
julia> sqrt(2)1.4142135623730951
julia> sqrt(3)1.7320508075688772

平方と平方根を同じプロットに描いてみよう. 直線 $y=x$ に対して,鏡の関係になっている.

using Plots
#gr() #pythonplot()
plot(aspect_ratio=:equal)

xs = 0:0.01:3
plot!(xs, xs .^ 2, label = "square")
plot!(xs, sqrt.(xs), label = "square root")
plot!(xs, xs, lc=:black, lw = 0.5, label = "y=x")
xlims!(-0.2, 2.2)
ylims!(-0.2, 2.2)
vline!([1], lc = :black, lw = 0.5)
hline!([1], lc = :black, lw = 0.5)
Note

負の数 $x < 0$ を関数 sqrt の引数(ひきすう)に与えると,例外(exception)が発生する.が,複素数を引数として与えると,複素数として計算できる(複素数は,もっと後の回で説明する).→ ▶ 負の数に対する平方根

julia> sqrt(-1) # DomainErrorERROR: DomainError with -1.0:
sqrt was called with a negative real argument but will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).
julia> sqrt(complex(-1)) # 複素数を引数に与える0.0 + 1.0im

▼ 立方根を描く

三乗すると $x$ になる数を,$x$ の立方根(cube root of $x$ )という. 関数 cbrt(x)x の立方根を求める関数である.

立方と立方根を同じプロットに描いてみよう. 直線 $y=x$ に対して,鏡の関係になっている.

using Plots
#gr() #pythonplot()
plot(aspect_ratio=:equal)

xs = 0:0.01:3
plot!(xs, xs .^ 3, label = "cubic")
plot!(xs, cbrt.(xs), label = "cube root")
plot!(xs, xs, lc=:black, lw = 0.5, label = "y=x")
xlims!(-0.2, 2.2)
ylims!(-0.2, 2.2)
vline!([1], color = :black, lw = 0.5)
hline!([1], color = :black, lw = 0.5)

平方と平方根,立方と立方根を,同じプロットに描こう. 点 $(1,1)$ で,曲線が交差している.

using Plots
#gr() #pythonplot()
plot(aspect_ratio=:equal)

xs = 0:0.01:3
plot!(xs, xs .^ 2, label = "square")
plot!(xs, sqrt.(xs), label = "square root")
plot!(xs, xs .^ 3, label = "cube")
plot!(xs, cbrt.(xs), label = "cube root")
plot!(xs, xs, lc=:black, lw = 0.5, label = "y=x")
xlims!(-0.2, 2.2)
ylims!(-0.2, 2.2)
vline!([1], lc=:black, lw = 0.5)
hline!([1], lc=:black, lw = 0.5)

▼ 一般の冪乗根を描く

一般に,正数 $x > 0$$2$ 以上の整数 $n$ に対して,$y^n = x$ の解, すなわち,$y = \sqrt[n]{x} = x^{\dfrac{1}{n}}$ を,$x$$n$ 乗根(root of $n$-th power, $n$-th root)という.$n$ を指定せずに,冪乗根(べきじょうこん)あるいは冪根(べきこん)と総称する. 「冪」の代わりに「巾」の略字を当てることもある.

using Plots
#gr() #pythonplot()
plot(
   legend=:topleft,
   aspect_ratio=:equal)

xs = 0:0.01:3
plot!(xs, xs .^ (1 / 2), label = "n=2")
plot!(xs, xs .^ (1 / 3), label = "n=3")
plot!(xs, xs .^ (1 / 4), label = "n=4")
plot!(xs, xs .^ (1 / 5), label = "n=5")
xlims!(-0.2, 2.2)
ylims!(-0.2, 2.2)
hline!([1], color = :black, lw = 0.5)
vline!([1], color = :black, lw = 0.5)

指数 $n$ で繰り返してみる.縦軸・横軸とも対数表示にする.

using Plots
#gr() #pythonplot()
plot(
   legend=:topleft,
   xscale=:log10, yscale=:log10)

xs = 0:0.01:10
for n = 2:5
   plot!(xs, xs .^ (1 / n),
      label = "y=x^(1/" * string(n) * ")")
end
xlims!(0.1, 10.0)
ylims!(0.1, 10.0)
hline!([1], color = :black, lw = 0.5)
vline!([1], color = :black, lw = 0.5)

▼ 対数関数を描く

数式Julia
a > 0$\log_{a}{x}$log(a,x)
$2$$\log_{2}{x}$log2(x)
$e$$\log{x}$, $\ln{x}$log(x)
$10$$\log_{10}{x}$log10(x)

▼ 自然対数

正の数 $x>0$ に対して,$x=e^y$ を満たす数 $y$ を,$x$ の自然対数(natural logarithm of $x$,Napierian logarithm,あるいは単に,logarithm)といい,$\log{x}$ と書く.

関数 log(x)は,自然対数を求める関数である.

julia> log(1)0.0
julia> log(ℯ)1
julia> log(ℯ^2)2.0

指数関数を,まず線形なプロットで描く.

using Plots
#gr() #pythonplot()
plot()

xs = 0.1:0.01:100
plot!(xs, log.(xs))

今度は,片対数プロットで描く. $x$ 軸を対数で表示すると,直線で表示される.

# 続けて
plot!(xscale=:log10)
plot!(xs, log.(xs))
Note

数学と同様,負の数に対する対数関数は定義されていない.引数に負数を与えると例外が起こる.

julia> log(-1) # DomainError
ERROR: DomainError with -1.0:

数学では $\log$関数を複素数の引数に拡張できる(複素関数論で習う).

結果は,$\log(-1) = i(1+2n)\pi$ ($n$ は整数)である. Juliaでも,複素数の -1 を引数として与えると,$n=0$に対応する値が得られる.

julia> log(complex(-1))  # 複素数を引数に与える0.0 + 3.141592653589793im

▼ 対数関数

正の数 $a > 0$ に対して,$x=a^y$ を満たす数 $y$ を, 底 $a$ に対する $x$ の対数(logarithm of $a$ to base b; base $a$ logarithm of $x$ )といい,$\log_{a}{y}$ と書く.

関数 log(a,y) のように,引数(ひきすう)2つを与えると, 底 $a$ に対する $x$ の対数が得られる.

片対数プロットを描く.$\log_{a}{1}=0$ で曲線が交差する.

using Plots
#gr() #pythonplot()
plot(
   legend=:topleft,
   xscale=:log10)

xs = 0.1:0.01:100
plot!(xs, log.(2, xs), label = string(2))
plot!(xs, log.(xs), label = string(ℯ))
plot!(xs, log.(3, xs), label = string(3))
plot!(xs, log.(10, xs), label = string(10))
hline!([0], color = :black, lw = 0.5)
vline!([1], color = :black, lw = 0.5)

底を for 文で変えてみる.

using Plots
#gr() #pythonplot()
plot(
   legend=:topleft,
   xscale=:log10)

xs = 0.1:0.01:100
for a in [2, ℯ, 3, 10]
   plot!(xs, log.(a, xs), label = string(a))
end
hline!([0], color = :black, lw = 0.5)
vline!([1], color = :black, lw = 0.5)

$2$$10$ に対しては,それぞれ関数 log2log10 が用意されている.

using Plots
#gr() #pythonplot()
plot(
   legend=:topleft,
   xscale=:log10)

xs = 0.1:0.01:100
plot!(xs, log2.(xs), label = "log2")
plot!(xs, log.(xs), label = "log")
plot!(xs, log10.(xs), label = "log10")
hline!([0], color = :black, lw = 0.5)
vline!([1], color = :black, lw = 0.5)

関数名で繰り返してみる.

using Plots
#gr() #pythonplot()
plot(
   legend=:topleft,
   xscale=:log10)

xs = 0.1:0.01:100
for f in [log2, log, log10]
   plot!(xs, f.(xs), label = string(f))
end
hline!([0], color = :black, lw = 0.5)
vline!([1], color = :black, lw = 0.5)

▲ 練習:色々な連続曲線を描く

ここまで紹介した関数を使って,色々な連続曲線を描いてみよ. Jupyter notebookの Markdown セルを用いて,説明文も加えよ.

★ 今回のまとめ

  • Jupyter Notebookを用いたテキスト入力(Markdownセル)
  • 実数全域で定義された関数
    • 正弦・余弦関数
    • 楕円
    • 極座標で著された曲線
      • アルキメデスの渦
      • 花曲線
    • 指数関数
  • 正数を定義域とする関数
    • 平方根・立方根・冪乗根
    • 対数関数
  • ダブルYプロット
    • ダブルYプロットの作成
    • ダブルYプロットに共通な凡例の作成
    • 描画領域の分割