今回は、「Pythonを使って数学の視覚化をする」シリーズとして、波の形を描く「三角関数」に挑戦します。
これまでに学習したmathモジュールの計算能力と、matplotlibのグラフ描画能力を使って視覚化しましょう。

角度の変換(ラジアン)とサイン・コサイン

三角関数と聞いて思い浮かぶのは、サイン(\(y = \sin(x)\))とコサイン(\(y = \cos(x)\))という数式です。これらは、角度の変化に合わせて波のように上がったり下がったりする滑らかなグラフになります。

サインとコサインはどこで使うか

「そもそも、サインやコサインは何に使うのか?」と思うかもしれません。これらは、角度から「長さ」や「座標」を計算するのに不可欠な数式です。例えば、地図アプリで「自分の現在地から北東(45度)の方向に100メートル進んだ場所」の正確な座標を計算するような場面で、\(\sin\)と\(\cos\)が使われています(具体的な計算プログラムは記事の後半で紹介します)。

Pythonでこれらの計算を行うには、mathモジュールに用意されているmath.sin()math.cos()を使います。ここで一つ重要なルールがあります。私たちが普段使っている「0度~360度」という角度の数字をそのまま計算に使うことはできません。計算を行う前に必ずmath.radians() を使って、「ラジアン」という別の単位に変換する必要があります。

では、実際にやってみましょう。
Google Colaboratory (Colab) を開いて新しいノートブックを作成し、サイン波とコサイン波を描くプログラムを書いてみます。

import matplotlib.pyplot as plt
import math

# x軸のデータを用意する(0度から360度までの整数のリスト)
x_data = list(range(0, 361))

# 角度をラジアンに変換し、サインとコサインの値を計算する
y_sin = [math.sin(math.radians(x)) for x in x_data]
y_cos = [math.cos(math.radians(x)) for x in x_data]

# グラフを描画し、それぞれに名前(label)をつける
plt.plot(x_data, y_sin, label="sin(x)")
plt.plot(x_data, y_cos, label="cos(x)")

# 凡例(ラベルの説明)を表示する
plt.legend()

# グラフにグリッド(目盛り線)を表示する
plt.grid(True)

# グラフを画面に表示する
plt.show()

とセルに入力して実行してみましょう。すると結果は

サイン、コサインのグラフ

のように表示されます。

プログラムの解説(サインとコサインの波)

  • モジュールの読み込み(1~2行目): グラフを描画するmatplotlib.pyplot と、計算を行う math モジュールを準備します。
  • x軸データの準備(5行目): range(0, 361) を使い、0から360までの角度データが入ったリストを作成しています。
  • データの計算(8~9行目): 内包表記を使っています。リストから角度を1つずつxに取り出し、まず math.radians(x) でラジアンに変換してから、math.sin()math.cos() で計算を行い、結果のリストを作成しています。
  • グラフの描画(12~13行目): plt.plot() を2回実行して波を重ねて描き、labelでそれぞれの線に数式の名前をつけています。
  • 装飾と表示(16~22行目): plt.legend() で凡例を表示し、plt.grid(True) で背景に目盛り線を入れることでグラフを見やすくし、最後にplt.show() で出力しています。

タンジェントと逆数

サイン・コサインに次いで挙げられるのが、タンジェント\(y = \tan(x)\)です。タンジェントは、「角度と距離から、建物の高さを求める」といった測量の計算などで活躍する関数です。

さらに、これら3つの関数の「逆数(分母と分子をひっくり返したもの)」となる、3つの仲間が存在します。

  • コセカント(csc): サインの逆数\(y = \frac{1}{\sin(x)}\)
  • セカント(sec): コサインの逆数\(y = \frac{1}{\cos(x)}\)
  • コタンジェント(cot): タンジェントの逆数\(y = \frac{1}{\tan(x)}\)

Pythonのmathモジュールには、math.tan() は用意されていますが、コセカントやセカントといった逆数を直接求める専用の関数はありません。しかし、数式の通りに、単純に「1を元の関数で割り算する」ようにプログラムを書けば、これらの逆数の値も簡単に計算することができます。

逆数の関数はどこで使うのか

「わざわざ逆数にした関数は何に使うのか?」と思うかもしれません。実は、これらは複雑な割り算の数式を、シンプルな掛け算に直すために活躍します。

例えば、直角三角形の形をした坂道で、「高さ」は分かっているけれど「斜辺(坂道そのものの長さ)」を知りたい場面を想像してみてください。サイン(\(\sin\))を使うと\(斜辺 = 高さ \div \sin(角度)\) という割り算の式になります。しかし、あらかじめ用意されたコセカント(\(\csc\))の数字を使えば\(斜辺 = 高さ \times \csc(角度)\) のように掛け算だけでスッキリと答えを出すことができます(具体的な計算プログラムは記事の後半で紹介します)。

では、実際にやってみましょう。
Colabの新しいセルに、基本の3つの関数と、逆数の3つの関数、合計6つの関数をすべて計算して同時にグラフに描画するプログラムを書いてみます。

この時、タンジェントや逆数の関数は、特定の角度(0度や90度など)の時に「0で割り算をしてしまう」という数学的なエラーが発生してしまいます。それを防ぐため、エラーの原因になる角度を除外する処理と、グラフが見辛くならないようにY軸の表示範囲をplt.ylim(-5, 5)で制限する処理を追加します。

import matplotlib.pyplot as plt
import math

# 0による割り算エラーを防ぐため、90で割り切れる角度を除外して1~359までのリストを作る
x_data = [x for x in range(1, 360) if x % 90 != 0]

# 3つの基本関数のデータを計算する
y_sin = [math.sin(math.radians(x)) for x in x_data]
y_cos = [math.cos(math.radians(x)) for x in x_data]
y_tan = [math.tan(math.radians(x)) for x in x_data]

# 3つの逆数関数のデータを割り算で計算する
y_csc = [1 / math.sin(math.radians(x)) for x in x_data]
y_sec = [1 / math.cos(math.radians(x)) for x in x_data]
y_cot = [1 / math.tan(math.radians(x)) for x in x_data]

# 6つのグラフを描画し、それぞれに名前(label)を付ける
plt.plot(x_data, y_sin, label="sin(x)")
plt.plot(x_data, y_cos, label="cos(x)")
plt.plot(x_data, y_tan, label="tan(x)")
plt.plot(x_data, y_csc, label="csc(x)")
plt.plot(x_data, y_sec, label="sec(x)")
plt.plot(x_data, y_cot, label="cot(x)")

# グラフが無限大に伸びて見辛くなるのを防ぐため、Y軸の範囲を-5から5に制限する
plt.ylim(-5, 5)

# 凡例と目盛り線を表示する
plt.legend()
plt.grid(True)

# グラフを画面に表示する
plt.show()

とセルに入力して実行して実行してみましょう。すると結果は

基本と逆数の三角関数のグラフ

のように表示されます。

プログラムの解説(6つのグラフの比較)

  • エラー回避のデータ準備(5行目): if x % 90 != 0 という条件付き内包表記を使い、90、180、270といった「0での割り算(ゼロ除算)」を引き起こす角度をリストからあらかじめ除外しています。
  • 逆数の計算(13~15行目): 専用の関数がないため、 1/ math.sin(...) のように、元の関数を使って割り算の式を書くことで逆数を計算しています。
  • Y軸の制限(26行目): plt.ylim(-5, 5) を使うことで、グラフの縦軸(Y軸)の表示範囲を-5から5の間に固定しています。実はコンピューターで計算する際、例えば90度をラジアンに変換してコサインを計算すると、厳密な「0」ではなく極めて0に近い微小な値(浮動小数点数の誤差)になります。これで1を割ってしまうと、極端に大きな数値になってしまいます。この制限を書かないと、一部のデータが極端に大きな数値になり、グラフ全体がつぶれて見えなくなってしまいます。

角度を逆算する「逆関数」

ここで、勘違いしやすいポイントがあります。

先ほど紹介した「逆数」は、計算を楽にするためのものでした。それとはまったく別に、「比率や長さから『角度』を逆算して求める」ための機能があり、これを「逆関数(Inverse)」と呼びます。

  • アークサイン(arcsin): サインの逆関数。
  • アークコサイン(arccos): コサインの逆関数。
  • アークタンジェント(arctan): タンジェントの逆関数。

数学の教科書では、アークサインのことを\(\sin^{-1}(x)\)と表記することがあります。これが原因で、「逆関数」と「逆数(コセカント)」を同じものだと混同してしまうかもしれませんが、全くの別物ですので注意してください。

Pythonには math.asin(), math.acos(), math.atan() が用意されています。ここでは、アークタンジェント(\(y = \arctan(x)\))のグラフを描画してみましょう。

import matplotlib.pyplot as plt
import math

# xのデータを用意する(-10から10までの範囲を細かく刻む)
x_data = [x * 0.1 for x in range(-100, 101)]

# math.atan() を使ってアークタンジェントを計算する
y_atan = [math.atan(x) for x in x_data]

# グラフを描画する
plt.plot(x_data, y_atan, label="arctan(x)")

plt.legend()
plt.grid(True)
plt.show()

とセルに入力して実行してみましょう。すると結果は

アークサインのグラフ

のように表示されます。波の形とは違い、緩やかなS字を描きながら一定の値に近づいてくグラフが表示されます。

プログラムの解説(アークタンジェントの描画)

  • 細かいデータの準備(5行目): 内包表記を使って、-10から10までの数値を0.1刻みで作成しています(-100から100までの整数に0.1を掛けることで小数を作り出しています)。
  • 逆関数の計算(8行目): math.atan(x) を使い、与えられた数値(比率)からラジアン角度を逆数するアークタンジェントの計算を行っています。

双曲線関数

最後に、通常の三角関数とよく似た「双曲線関数(そうきょくせんかんすう)」を紹介します。通常の三角関数が「円」をベースにしているのに対し、こちらは「双曲線」をベースにしています。関数名の最後に「h」をつけて表します。

  • ハイパボリック・サイン(\(sinh\))
  • ハイパボリック・コサイン(\(cosh\))
  • ハイパボリック・タンジェント(\(tanh\))

例えば\(cosh(x)\)のグラフを描くと、「両端を持って垂らした曲線(懸垂線)」と同じ形になります。

では、実際にやってみましょう。
Colabの新しいセルに、\(cosh(x)\) でロープの垂れ下がる曲線を描画するプログラムを書いてみます。

import matplotlib.pyplot as plt
import math

# xのデータを用意する(-3から3までの範囲を細かく刻む)
x_data = [x * 0.1 for x in range(-30, 31)]

# math.cosh()を使ってハイパボリック・コサインを計算する
y_cosh = [math.cosh(x) for x in x_data]

# グラフを描画する
plt.plot(x_data, y_cosh, label="cosh(x)")

plt.legend()
plt.grid(True)
plt.show()

とセルに入力して実行してみましょう。すると結果は

ハイパボリック・コサインのグラフ

のように表示されます。まるでネックレスが垂れ下がっているような曲線が描画されます。

プログラムの解説(双曲線関数の描画)

  • データの準備(5行目): 内包表記を使って、-3から3までの数値を0.1刻みで作成しています。
  • 双曲線関数の計算(8行目): math.cosh(x) を使って計算しています。

[補足] 三角関数を使った実用的な計算プログラム

視覚化からは少し離れますが、三角関数が実際にどんな計算で役立つのか、実用的なプログラムの例を紹介します。

1.目的地までの座標を計算する(サイン・コサインの利用)

地図アプリやGPSなどで、「斜め45度の方向に、10メートル進む」といった場合、画面上のX座標(東西の動き)とY座標(南北の動き)がそれぞれどれくらい変化するのかを計算する必要があります。斜めの移動距離と角度が分かっているとき、横の動き(底辺)はコサイン(\(\cos\))、縦の動き(対辺)はサイン(\(\sin\))を使って計算します。

  • \(X方向の移動量 = 距離 \times \cos(角度)\)
  • \(Y方向の移動量 = 距離 \times \sin(角度)\)
import math

distance = 10 # 移動する距離
angle = 45 # 移動する角度

# 角度をラジアンに変換する
rad = math.radians(angle)

# cosとsinを使ってX方向・Y方向の移動量を計算する
x_move = distance * math.cos(rad)
y_move = distance * math.sin(rad)

print(f"X方向に約{x_move:.2f}、Y方向に約{y_move:.2f}移動します。")

とセルに入力して実行してみましょう。すると結果は

X方向に約7.07、Y方向に約7.07移動します。

と表示されます。

プログラムの解説(座標の計算)

  • 角度の変換(7行目): math.radians() で45度をラジアンに変換しています。
  • 座標の計算(10~11行目): distance * math.cos(rad) で横方向への移動量を、distance * math.sin(rad) で縦方向への移動量を求めています。

2. 木(建物)の高さを計る(タンジェントの利用)

ある木から10メートル離れた場所に立ち、木のてっぺんを見上げたら角度が30度でした。自分の目の高さを無視した場合、木そのものの高さは何メートルでしょうか。底辺(距離)と角度から、高さ(対辺)を求めるには、タンジェント(\(\tan\))を使って
(\(高さ = 距離 \times \tan(角度)\))
と計算します。

import math

distance = 10 # 木までの距離(メートル)
angle = 30 # 見上げた角度(度)

# 角度をラジアンに変換してtanを計算し、距離を掛ける
height = distance * math.tan(math.radians(angle))

print(f"木の高さは約{height:.2f}メートルです。")

とセルに入力して実行してみましょう。すると結果は

木の高さは約5.77メートルです。

と表示されます。

プログラムの解説(高さの計算)

  • タンジェントの計算(7行目): math.tan() にラジアンに変換した30度を渡し、それに距離を掛けることで、高さを割り出します。

3. 坂道の長さを求める(逆数・コセカントの利用)

先ほどの説明で挙げた「高さと角度から斜辺(坂道の長さ)を求める」計算を、サインの逆数であるコセカント(\(\csc\))を使ってやってみましょう。高さが5メートル、角度が15度の坂道があります。坂道そのものの長さは何メートルでしょうか。
(\(斜辺 = 高さ \times \csc(角度)\))
(\(\csc(x) = \frac{1}{\sin(x)}\))で計算します。

import math

height = 5 # 坂の高さ(メートル)
angle = 15 # 坂の角度

# コセカント(csc)を1 / sin で計算する
csc_value = 1 / math.sin(math.radians(angle))

# 高さにコセカントを掛けて斜辺を求める
slope_length = height * csc_value

print(f"坂道の長さは約{slope_length:.2f}メートルです。")

とセルに入力して実行してみましょう。すると結果は

坂道の長さは約19.32メートルです。

と表示されます。

プログラムの解説(斜辺の計算)

  • 逆数の計算(7行目): 1 / math.sin() という割り算の式を書くことで、コセカントの値を計算して変数csc_valueに代入しています。
  • 掛け算による算出(10行目): 高さにコセカントの値を掛けて斜辺の長さを算出します。

4. 長さと高さから「角度」を逆算する(逆関数の利用)

「距離と高さは分かっているけれど、角度が知りたい」という場合は、逆関数を使います。計算結果は「ラジアン」で返ってくるため、「度」に戻すmath.degrees() という関数とセットで使います。

アークタンジェントを利用して10メートル離れた場所から、高さ10メートルの木を見上げる角度を計算してみましょう。

import math

distance = 10 # 木までの距離
height = 10 # 木の高さ

# 高さを距離で割って比率を出し、math.atan()でラジアンの角度を求める
rad = math.atan(height / distance)

# 求まったラジアンを「度(Degrees))」に戻す
angle = math.degrees(rad)

print(f"木を見上げる角度は{angle:.1f}度です。")

とセルに入力して実行してみましょう。すると結果は

木を見上げる角度は45.0度です。

と表示されます。

プログラムの解説(アークタンジェントの利用)

  • 比率からラジアンを逆算(7行目): まず height / distance で「高さと距離の比率」を計算します。その比率を math.atan() に渡すことで、対応する角度(ラジアン)が逆算されます。
  • ラジアンを度に戻す(10行目): math.degrees() を使い「度(度数法)」に変換します。

次にアークサインを利用して長さが20メートルの坂道があり、登り切った時の高さが5メートルの時の傾斜角度を求めてみましょう。

import math
slope_length = 20 # 坂道の長さ(斜辺)
height = 5 # 坂道の高さ(対辺)

# 高さを斜辺で割って比率を出し、math.asin()でラジアンの角度を求める
rad = math.asin(height / slope_length)

angle = math.degrees(rad)

print(f"スロープの傾斜角度は約{angle:.1f}度です。")

とセルに入力して実行してみましょう。すると結果は

スロープの傾斜角度は約14.5度です。

と表示されます。

プログラムの解説(アークサインの利用)

  • 比率からラジアンを逆算(7行目): height / slope_length で比率を出しています。

5.ロープが垂れ下がる高さを計算する(双曲線関数の利用)

\(\cosh\)の式(\(y = a \times \cosh(x/a)\))を使えば、ロープがどれくらい垂れ下がっているかの高さを計算することができます。

import math

a = 10 # ロープの張り具合などを表す数値
x = 5 # 中心から横に移動した距離(メートル)

# 懸垂線の数式を使って高さを計算する
height = a * math.cosh(x / a)

print(f"中心から{x}メートル横に移動した地点のロープの高さは、約{height:.2f}メートルです。")

とセルに入力して実行してみましょう。すると結果は

中心から5メートル横に移動した地点のロープの高さは、約11.28メートルです。

と表示されます。

プログラムの解説(懸垂線の計算)

  • 双曲線関数による計算(7行目): a * math.cosh(x / a) というカテナリー曲線の公式をそのままプログラムに書き起こしています。

まとめ

今回は、プログラミングを使って数学の「三角関数」を視覚化する方法について解説しました。

  • 基本: math.sin() など。GPSの座標計算などに使われる。
  • 逆数: \csc, \sec, \cot。専用関数はないため1 / math.sin(x) のように計算する。
  • 逆関数: \arcsin, \arccos, \arctan。比率から「角度」を逆算するもの。Pythonではmath.asin() などを使う。
  • 双曲線関数: \sinh, \cosh, tanh。\coshはロープが垂れ下がる曲線(懸垂線)を描く。
  • ラジアンへの変換: math.sin() などの計算の前に、必ず math.radians() で角度を変換する。
  • エラーの回避: 0での割り算が起きないように、あらかじめ if 文などで特定のデータを除外しておく。
  • 表示範囲の制限: plt.ylim(最小値, 最大値) を使うと、グラフの縦軸の範囲を見やすく整えることができる。

名前が似ていて混乱しやすい「逆数」と「逆関数」も、こうして実際にプログラムを書いてみると、役割が違うことが分かります。
数式だけを見ていると難しく感じる三角関数も、このようにグラフにして並べてみたり、実際の距離の計算に使ってみたりすると、数学の便利さを直感的に感じることができます。ぜひ色々と数字を変えて試してみてください。

open-in-colab

今回はこれで終了です。
今回のサンプルを用意したので、もし必要な場合は上の「Open in Colab」と書いてあるボタンをクリックしてください。なおそのままだと編集不可なので編集をしたい場合は「ドライブにコピー」をクリックしてコピーしてください。
なおGoogle ColaboratoryについてわからなかったらGoogleColaboratoryを使ってみよう_導入編をご覧ください。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA