三角関数#

三角比#

直角三角形は、内角θの値を固定するとすべて相似な形となるため、x/ry/rなどの辺の長さ同士の比は一定になる。

Hide code cell source
import numpy as np
import matplotlib.pyplot as plt

base = [0, 0]
x = [2, 0]
r = [2, 1]

fig, ax = plt.subplots(figsize=[4,3])
ax.plot([base[0], x[0]], [base[1], x[1]], label=r"$x$", color="steelblue")
ax.text(x=(x[0] - x[1])/2, y=x[1]+0.01, s=r"$x$", color="steelblue")

ax.plot([base[0], r[0]], [base[1], r[1]], label=r"$r$", color="green")
ax.text(x=1, y=0.5, s=r"$r$", color="green", ha="right")

ax.plot([x[0], r[0]], [x[1], r[1]], label=r"$y$", color="orange")
ax.text(x=x[0]-0.02, y=(r[1]-x[1])/2, s=r"$y$", color="orange", ha="right")

ax.legend()
fig.show()
../../../_images/91faa53fea14b35c3ee0362a35a840825f2239578214fd5860488bb4fbe940bb.png

この値を三角比と呼び、角度θの値によって決まるものとなる。

sinθ=yrcosθ=xrtanθ=yx=sinθcosθ

三角関数#

三角比の定義では、直角三角形の内角となりうる0から90の間の値しかとれないが、それ以外の値もとれるように定義を拡張したものが三角関数である。

r=1の場合、sinθ=y1=y,cosθ=x1=xとなり扱いやすい。これを利用して、半径1、中心が原点の円(単位円)の円周上の点、x軸の正の向きからの角度がθの点のy座標をsinθx座標をcosθと定義する。

Hide code cell source
theta = (np.arange(0, 360) * np.pi / 180)
y = np.sin(theta)
x = np.cos(theta)

# base
fig, ax = plt.subplots(figsize=[4, 4])
ax.plot(x, y)
ax.axhline(0, color="gray")
ax.axvline(0, color="gray")

# line
theta = (120 * np.pi / 180)
y = np.sin(theta)
x = np.cos(theta)
ax.plot([0, x], [0, y], color="darkorange")
ax.text(x - 0.1, y + 0.1, r"($\cos \theta, \sin \theta$)", color="darkorange", ha="center")

fig.show()
../../../_images/50795741212048598ed231aebcf94025bc93e628062bd225ff779c1eac80cb03.png
Hide code cell source
fig, ax = plt.subplots(figsize=[6,2])

width = 2 * np.pi
x = np.linspace(-width, width, 100)
ax.plot(x, np.sin(x), label=r"$\sin x$")
ax.plot(x, np.cos(x), label=r"$\cos x$")

ax.axhline(0, color="gray", alpha=0.5)

step_size = np.pi / 2
ticks = np.arange(-width, width + step_size, step_size)  # 0から2πまでπ/2刻み
tick_labels = [r"-2$\pi$", r"-$\frac{3\pi}{2}$", r"-$\pi$", r"-$\frac{\pi}{2}$", r"$0$", r"$\frac{\pi}{2}$", r"$\pi$", r"$\frac{3\pi}{2}$", r"$2\pi$"]
ax.set_xticks(ticks)
ax.set_xticklabels(tick_labels)

ax.grid(True)
ax.legend()
fig.show()
../../../_images/75497662717aa72c2bdfa03fd1cfd6f98fc4af8e52ac933616c297f692fb3b65.png
Hide code cell source
fig, ax = plt.subplots(figsize=[6,2])

r = np.array([0, 0.5, 1, 1.5, 2])
r = (-r).tolist() + r.tolist()
ticks = [c * np.pi for c in r]

x = np.linspace(-6.5, 6.5, 100)
ax.plot(x, np.tan(x), label=r"$\tan x$")
ax.set(xticks=ticks)
ax.grid(True)
ax.legend()
fig.show()
../../../_images/763407829f4d224d538e3f23327addec3694ab1f3dfd1a12634b0bef8f1ffb1d.png

逆三角関数#

三角関数の逆関数のことを逆三角関数という。

arcsinx=sin1xarccosx=cos1xarctanx=tan1x
Hide code cell source
fig, ax = plt.subplots(figsize=[2,3])

x = np.linspace(-np.pi, np.pi, 100)
ax.plot(np.sin(x), x, label=r"$x = \sin y$")
ax.plot(np.cos(x), x, label=r"$x = \cos y$")
ax.legend()
fig.show()
../../../_images/2c377381ee9cd9289a23a68c65270730945a3d62a61bb4658f7e97dd5abd45eb.png

例:内積から角度を取り出す#

cosθ=abab

で、ここでθはラジアンであり、コサイン類似度cosθ=0のときはθ=arccosθ=π21.571

ラジアンを度(degree)に戻すにはdegree=θ×(180/π)

Hide code cell source
a = np.array([0, 1])
b = np.array([1, 0])

fig, ax = plt.subplots()
ax.plot([0, a[0]], [0, a[1]], color="steelblue")
ax.plot([0, b[0]], [0, b[1]], color="steelblue")
ax.text(a[0] * 1.01, a[1] * 1.01, f"a={a}", color="steelblue")
ax.text(b[0] * 1.01, b[1] * 1.01, f"b={b}", color="steelblue")

cos_theta = (a @ b) / (np.linalg.norm(a) * np.linalg.norm(b))  # cos θ
theta = np.arccos(cos_theta)
degree = theta * (180 / np.pi)

ax.set(xlabel="x", ylabel="y", title=fr"$\cos \theta$ = {cos_theta:.1f}, $\theta= arccos \theta = ${theta:.3f}, degree={degree:.0f}")

fig.show()
../../../_images/6ee6c6a51fa2a662e27e02a58917b34cb593670717f9b487ee2ac9837339b10e.png

Note

内積やコサイン類似度との関係 三角比の定義式

sinθ=yrcosθ=xr

の両辺にrを掛けると、

y=rsinθx=rcosθ

となる。

2つのベクトルa,bのなす角度をθとすると、内積ab

ab=||a|| ||b||cosθ

と定義される。

Hide code cell source
a = np.array([4, 2])
b = np.array([1, 2])

fig, ax = plt.subplots()
ax.plot([0, a[0]], [0, a[1]], color="steelblue")
ax.plot([0, b[0]], [0, b[1]], color="steelblue")
ax.text(a[0] * 1.01, a[1] * 1.01, f"a={a}", color="steelblue")
ax.text(b[0] * 1.01, b[1] * 1.01, f"b={b}", color="steelblue")

b_ = ((np.linalg.norm(b) / np.linalg.norm(a)) * a).astype(int)
ax.plot([0, b_[0]], [0, b_[1]], color="darkorange")
ax.plot([b[0], b_[0]], [b[1], b_[1]], color="darkorange", linestyle=":")
ax.text(1.5, 1.5, "|b| sin θ", color="dimgray")

ax.text(b_[0] * 1.07, b_[1] * 0.95, f"b'={b_}", color="darkorange")
ax.text(*(b_ * 0.5), "|b| cos θ ?", color="dimgray")


fig.show()
../../../_images/c173fb01df49caa9240745764b667386ba6d1b706c1a735718ab1b2b34177ef4.png

bからaへ垂線をたらして射影したものの長さは||b||sinθとなる。これは単位円におけるy=rsinθに相当する(ノルム||b||はベクトルの長さのため)

同様にx=rcosθからy=||b||cosθとなる

はずだが…?

cos_theta = (a @ b) / (np.linalg.norm(a) * np.linalg.norm(b))  # cos θ
b_length = np.linalg.norm(b) * cos_theta # |b| cos θ
print(b_length, np.linalg.norm(b_)) ## 一致しない
1.7888543819998315 2.23606797749979
cos_theta = (a @ b) / (np.linalg.norm(a) * np.linalg.norm(b))  # cos θ
theta = np.arccos(cos_theta)
b_length = np.linalg.norm(b) * np.sin(theta) # |b| sin θ
print(b_length, np.linalg.norm(b - b_)) ## 一致しない
1.3416407864998743 1.4142135623730951

三角関数の基本的性質#

性質1

sin(x)=sinxcos(x)=cosxtan(x)=tanx

一般に f(x)=f(x) となる関数を 奇関数f(x)=f(x) となる関数を 偶関数 という。

sinx,tanx は奇関数, cosx は偶関数である

性質2(相互関係)

sin2x+cos2x=1
sin2θ=(yr)2=y2r2,cos2θ=(xr)2=x2r2
sin2θ+cos2θ=y2r2+x2r2=x2+y2r2

三平方の定理よりx2+y2=r2なので

sin2θ+cos2θ=x2+y2r2=1

性質3 (加法定理)

sin(x±y)=sinxcosy±cosxsinycos(x±y)=cosxcosysinxsinytan(x±y)=tanx±tany1tanxtany

性質4(2倍角の公式)

sin2θ=2sinθcosθcos2θ=12sin2θ=2cos2θ1tan2θ=2tanθ1tan2θ
証明
sin2θ=sin(θ+θ)=sinθcosθ+cosθsinθ( 加法定理 )=2sinθcosθ
cos2θ=cos(θ+θ)=cosθcosθsinθsinθ( 加法定理 )=cos2θsin2θ=2cos2θ1( 相互関係 )=12sin2θ( 相互関係 )
tan2θ=tan(θ+θ)=tanθ+tanθ1tanθtanθ( 加法定理 )=2tanθ1tan2θ