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

■ plot関数のフォーマット・パラメータ

PyPlot パッケージに含まれる関数 plot は, 複数回起動する毎に曲線の見た目を変える.

見た目を個別に変えるには,plot 関数のデータを指定した直後に, 文字列( fmt パラメータ)を指定する.

fmt パラメータは, 色,マーカー種類,線の見た目を,1文字ないし2文字で指定する. 指定しなければ,規定値が選ばれる.

・色を変える例

using PyPlot
xs = -10:0.1:10
plt.plot(xs, 9.0 .^ xs, "b", label = "b") # blue
plt.plot(xs, 8.0 .^ xs, "g", label = "g") # green
plt.plot(xs, 7.0 .^ xs, "r", label = "r") # red
plt.plot(xs, 6.0 .^ xs, "c", label = "c") # cyan
plt.plot(xs, 5.0 .^ xs, "m", label = "m") # magenda
plt.plot(xs, 4.0 .^ xs, "y", label = "y") # yellow
plt.plot(xs, 3.0 .^ xs, "k", label = "k") # black
plt.plot(xs, 2.0 .^ xs, "w", label = "w") # white (白背景では見えない)
plt.xlim(0, 3)
plt.ylim(0, 100)
plt.legend()

・マーカーの形を変える例. マーカーの色はすべて青とした

using PyPlot
xs = -2:0.2:2
ys = xs .^ 2
plt.plot(xs, ys, "b.", label = ".") # point
plt.plot(xs, ys .- 2, "b,", label = ",") # pixel
plt.plot(xs, ys .- 4, "bo", label = "o") # circle
plt.plot(xs, ys .- 6, "bs", label = "s") # square
plt.plot(xs, ys .- 8, "b*", label = "*") # star
plt.plot(xs, ys .- 10, "b+", label = "+") # plus
plt.plot(xs, ys .- 12, "bx", label = "x") # x
plt.plot(xs, ys .- 14, "bD", label = "D") # diamond
plt.plot(xs, ys .- 16, "bd", label = "d") # thin diamond
plt.xlim(-3, 5)
plt.legend(loc="upper right")

Note

plt.legend() 命令は,最適と考える位置に凡例を描く.キーワード引数 loc を用いると,凡例を描画する位置を指定できる。以下の整数または文字列で,大まかな位置を指定できる.(試してみよ) ・ 0 ,"best" ・ 1 ,"upper right" ・ 2 ,"upper left" ・ 3 ,"lower left" ・ 4 ,"lower right" ・ 5 ,"right" ・ 6 ,"center left" ・ 7 ,"center right" ・ 8 ,"lower center" ・ 9 ,"upper center" ・10 ,"center"

・線のスタイルを変える例

using PyPlot
xs = -2:0.2:2
ys = xs .^ 3 - xs .^ 2
plt.plot(xs, ys .- 0, "r-", label = "-")  # solid line
plt.plot(xs, ys .- 2, "r--", label = "--") # dashed line
plt.plot(xs, ys .- 4, "r-.", label = "-.") # dash-dot line
plt.plot(xs, ys .- 6, "r:", label = ":")  # dotted line plt.xlim(-2.2,2.2)

■ 0による除算

筆算では 0 による除算の結果は未定義である.

Julia では,0 による除算は,例外は発生せず, 「数でない数」 Inf, -Inf, NaN のどれかが得られる.

Inf は,無限大 Infinity に由来する. NaN は,数でない Not a Number に由来する.

julia> 1 / 0Inf
julia> -1 / 0-Inf
julia> 0 / 0NaN

▼ 関数が連続とは

関数が連続であるとは, 関数のグラフがつながっている,ちぎれていないことをいう.

「関数 $f(x)$$x=a$ で連続」とは,

\[\lim_{x \longrightarrow a} f(x)\]

が存在して,その値が $f(a)$ に等しいと定義される.

不連続とは,連続でないことである. ただし,不連続な関数の多くは,連続な部分(枝,branch)を含む,

この章では,主に,連続ではない関数のグラフを描く.

▼ 逆数関数を描く

逆数関数 $y=\dfrac{1}{x}$ を描いてみよう.

Note

逆数関数 reciprocal function という.逆関数 inverse function と区別されたい.

さて,$\dfrac{1}{0}$ の値は Inf であるが,plot 関数は「数でない数」をスキップして何も描かない.分母 $0$ の除算を特別扱いする必要はない.

逆数関数は,$x=0$ で不連続であり,$x$ の正負に対応して2つの枝を持つ.

using PyPlot
plt.axes().set_aspect("equal")

xs = -3:0.1:3
plt.plot(xs, 1.0 ./ xs)
plt.xlim(-3, 3)
plt.ylim(-3, 3)

続けて,$y=x$$y=-x$,水平線 $y = 0$,垂直線 $x = 0$,を追加しよう.

plt.plot(xs, xs, color = "k", lw = 0.5)
plt.plot(xs, -1 * xs, color = "k", lw = 0.5)
plt.axhline(0, color = "k", lw = 0.5)
plt.axvline(0, color = "k", lw = 0.5)

▲ 練習

(プログラミングでなく,数学の話題)

数学では「何らかの操作を行った結果が,元と重なること」を, その操作に対して対称である(symmetric)という.

上のグラフを観察すると,逆数関数は,いくつかの操作に対して対称であることがわかる.どのような操作か?

▼ 不連続な有理式を描く

有理関数とは,多項式(分子)を多項式(分母)で割った関数である.

以下の有理関数を描こう.

\[y = \dfrac{x^3+8}{x^3+3x^2-4x-12}\]

まず,分母を描く.

using PyPlot
xs = -10:0.1:10
qs = xs .^ 3 .+ 3xs .^ 2 .- 4xs .- 12
plt.plot(xs, qs)
plt.ylim(-20, 20)
plt.xlim(-4, 4)
plt.axhline(0, color = "k", lw = 0.5)
plt.axvline(-3, color = "k", lw = 0.5)
plt.axvline(-2, color = "k", lw = 0.5)
plt.axvline(2, color = "k", lw = 0.5)

分母は $x=-3, -2, 2$$0$ となるから, 上の有理関数は,この三点で不連続となる「可能性」がある.

では,上の有理関数を描いてみる. 逆数関数の描画と同じように,分母 $0$ となる場合を特別扱いする必要はない.

using PyPlot
xs = -10:0.05:10
ps = xs .^ 3 .+ 8
qs = xs .^ 3 .+ 3xs .^ 2 .- 4xs .- 12
ys = ps ./ qs
plt.plot(xs, ys)
plt.ylim(-10, 10)
plt.xlim(-4, 4)
plt.axhline(0, color = "k", lw = 0.5)
plt.axvline(-3, color = "k", lw = 0.5)
plt.axvline(2, color = "k", lw = 0.5)

実際には,$x=-2$ では不連続ではない. 分子・分母を共通項 $(x+2)$ で割れるからである.

もう少し,横軸の範囲を狭めて描く.

using PyPlot
xs = -10:0.05:10
ps = xs .^ 3 .+ 8
qs = xs .^ 3 .+ 3xs .^ 2 .- 4xs .- 12
ys = ps ./ qs
plt.plot(xs, ys)
plt.ylim(-10, 10)
plt.xlim(-3, 3)
plt.axhline(0, color = "k", lw = 0.5)
plt.axvline(-3, color = "k", lw = 0.5)
plt.axvline(-2, color = "k", lw = 0.5)
plt.axvline(2, color = "k", lw = 0.5)

▲ 練習

上の有理関数で,$x=-2$ に対する値を求めよ.

分子・分母は共通項 $(x+2)$ で割った関数のグラフを描き, 上のグラフと重なることを確かめよ.2つの曲線を比較するための描き方は,下の ▼ 周期関数 を参考にせよ(本章を通読してから取り組め).

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

  • 正接 $y = \tan{x} =\dfrac{\sin{x}}{\cos{x}}$
  • 余接 $y = \cot{x} =\dfrac{\cos{x}}{\sin{x}}$

ラジアン単位

正接 $\tan{x}$は,$\dfrac{\pi}{2}$ の奇数倍で不連続である.

余接 $\cot{x}$は,$\dfrac{\pi}{2}$ の偶数倍で不連続である.

using PyPlot
xs = -2pi:pi/360:2pi
plt.plot(xs, tan.(xs), label = "tan")
plt.plot(xs, cot.(xs), label = "cot")
plt.ylim(-1e1, 1e1)
plt.xlabel("radian")
plt.legend()

角度単位

using PyPlot
xs = -360:1:360
plt.plot(xs, tand.(xs), label = "tand")
plt.plot(xs, cotd.(xs), label = "cotd")
plt.xlabel("degree")
plt.ylim(-1e1, 1e1)
plt.legend()

▼ 周期関数

\[f(t+T) = f(t)\]

上式のように,横軸を $T$ だけ平行移動しても, 元の形に重なる関数を周期関数(periodic function)という. $T$ は,周期(period) と呼ばれる.

●▼ 周期関数を確認する

ラジアン単位の正接関数 tan は,周期 $2\pi$ である. 平行移動して重なることを,図示してみよう.

比較の基準となる曲線は fmt="bo"(blue, circle, 青い円)で描いた.

比較される曲線は fmt="r." (red, point, 赤い点)で描いた.

青い円の真ん中に,赤い点が描かれている.

using PyPlot

xs = -2pi:pi/18:2pi
plt.plot(xs, tan.(xs), "bo", label = "tan")
plt.plot(xs, tan.(xs .+ 2 * pi), "r.", label = "tan, shifted by 2pi")
plt.ylim(-1e1, 1e1)
plt.xlim(-1.2 * pi, 1.2 * pi)
plt.xlabel("radian")
plt.legend()

▼ 符号関数を描く

Base.sign - Function

関数 sign(x) は,

  • 条件 $x > 0$ なら $1$ を,
  • 条件 $x = 0$ なら $0$ を,
  • 条件 $x < 0$ なら $-1$ を,

それぞれ返す.

using PyPlot
xs = -6.4:0.1:6.4
plt.plot(xs, sign.(xs), ".")

三角関数と関数 sign とを組み合わると, 不連続な周期関数を作ることができる.

▶ 方形波を描く

2つの一定値を交互にとる周期関数を方形波(square wave)という.

using PyPlot
plt.plot(xs, cos.(xs), "r", label = "cos(x)")
plt.plot(xs, sign.(cos.(xs)), "b.", label = "sign(cos(x))")
plt.legend()

▲ 練習

  • 上の例の周期はいくつか?
  • 周期が 1 になるように,変更してみよ.グラフを描け.

▼ 絶対値関数

関数 abs(x)は,$x$ の絶対値を返す.

using PyPlot
plt.axes().set_aspect("equal")
xs = -1:0.1:1
plt.plot(xs, abs.(xs))

絶対値関数の符号を変えたり,平行移動すると,色々な山や谷の形を描くことができる.

using PyPlot
plt.axes().set_aspect("equal")

xs = -2pi:pi/18:2pi
# 符号を変える.山の形
plt.plot(xs, -abs.(xs), label = "-abs(x)")
# 縦軸の平行移動
plt.plot(xs, pi .- abs.(xs), label = "pi-abs(x)")
# さらに,横軸の平行移動
plt.plot(xs, pi .- abs.(xs .- pi), label = "pi-abs(x-pi)")
plt.legend()
plt.xlabel("x")
plt.axhline(0, color = "k", lw = 0.5)
plt.axvline(0, color = "k", lw = 0.5)
plt.axvline(pi, color = "k", lw = 0.5)

▼ クランプ関数

Base.Math.clamp

関数 clamp(x, lo, hi) は,上限と下限で制限する関数である. すなわち,$x$ の値が hi よりも大きければ hi を,lo よりも大きければ lo を返す. どちらでもなければ,そのままの値を返す.

using PyPlot
plt.axes().set_aspect("equal")
xs = -5:0.1:5
plt.plot(xs, clamp.(xs, -1, 2))
plt.xlim(-5, 5)
plt.ylim(-5, 5)

■ 床関数・天井関数

床関数 floor(x) は,$x$ 以下の最大の整数を返す.

天井関数 ceil(x) は,$x$ 以上の最小の整数を返す.

下のグラフで,整数 $x$ に対する関数の値を,よく観察せよ.

これらの関数は,■ 浮動小数点数から整数への変換 で用いられる.

using PyPlot
plt.axes().set_aspect("equal")

xs = -2.4:0.2:2.4
plt.plot(xs, ceil.(xs), "o", label = "ceil")
plt.plot(xs, floor.(xs), ".", label = "floor")
for x = -2:2
   plt.axvline(x, color = "k", lw = 0.5)
   plt.axhline(x, color = "k", lw = 0.5)
end
plt.xlim(-3.2, 3.2)
plt.ylim(-3.2, 3.2)

plt.legend()

▲ 練習

床関数または天井関数を用いて, 正の数を $1$ ので四捨五入するには,どうしたらよいか? $1$ の位での四捨五入とは,その数の小数点第一桁目が $5$ 以上であれば元の数に $1$ を加え,$5$ 未満であれば何もしない操作である.

プログラムを書いて,グラフを描き,確認してみよ. とくに,小数点以下が $0.5$ に等しい場合の結果を観察せよ.

Note

数字のおおよその値を表すために用いられる「四捨五入」は,科学技術分野では適当ではない.「数字の丸め方」は,日本工業規格 JIS Z8401 : 1999 (国際規格 ISO 31-0 : 1992 に相当)に定められている.JIS規格の全文は,たとえば,ここで読める.→ kikakurui Z8401-1999-01

▲ 練習

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

★ 今回のまとめ

  • plot 関数のフォーマットパラメータ
  • 0 による除算
  • 逆数関数
  • 不連続な有理関数
  • 正接・余接関数
  • 周期関数
  • 符号関数
  • 絶対値関数
  • 床関数・天井関数