三角関数のsin(サイン)、cos(コサイン)、tan(タンジェント)、聞いただけで「苦手かも…」と思った人もいるでしょう。
でも、Pythonを使えばたった1行のコードで三角関数が使えるって知っていましたか?
こんなことで困っていませんか?
- 数学の三角関数がよくわからない
- プログラムで角度の計算をしたい
- グラフやアニメーションを作りたい
- ゲームで回転や移動を計算したい
グラフ描画・物理シミュレーション・角度計算など、実は意外と多くの場面で役立つ三角関数。
この記事では、Pythonでsin, cos, tanを使う方法から応用例まで、初心者向けにわかりやすく解説します。
三角関数って何?【基本のおさらい】

三角関数とは
三角関数とは、角度と辺の長さの関係を表す関数です。
身近な例
- 坂道の傾斜角度
- 時計の針の位置
- 波の形
- 音楽の音波
直角三角形で理解しよう
/|
c / | b(高さ)
/ |
/θ___|
a(底辺)
三角関数の定義
- sin θ:高さ ÷ 斜辺 = b/c
- cos θ:底辺 ÷ 斜辺 = a/c
- tan θ:高さ ÷ 底辺 = b/a
覚えやすい語呂合わせ
「サイトコサタン」
- サイ(sin):サカサ(坂)のイ(高さ)
- コサ(cos):コウドウ(広道)のサ(幅)
- タン(tan):タカサ(高さ)とン(の)比
Pythonで三角関数を使うには?【mathモジュール】

mathモジュールの基本
Pythonで三角関数を使うには、まず標準ライブラリのmath
モジュールを使います。
基本の書き方
import math
# 三角関数の基本形
math.sin(角度) # サイン
math.cos(角度) # コサイン
math.tan(角度) # タンジェント
インポートの別の方法
# よく使う関数だけインポート
from math import sin, cos, tan, pi, radians, degrees
# こう書けば math. をつけなくてもOK
result = sin(radians(30))
重要:単位は「ラジアン」
Pythonの三角関数では、**角度の単位は「度」ではなく「ラジアン」**です。
ラジアンとは? ラジアンとは、円周上の角度をπ(パイ)を基準に表す単位です。
度とラジアンの対応表
度数 | ラジアン | 覚え方 |
---|---|---|
0° | 0 | スタート地点 |
30° | π/6 ≒ 0.52 | – |
45° | π/4 ≒ 0.79 | 4分の1 |
60° | π/3 ≒ 1.05 | – |
90° | π/2 ≒ 1.57 | 2分の1 |
180° | π ≒ 3.14 | 半円 |
360° | 2π ≒ 6.28 | 全円 |
度とラジアンの変換
import math
# 度 → ラジアン
angle_deg = 30 # 30度
angle_rad = math.radians(angle_deg)
print(f"{angle_deg}度 = {angle_rad:.3f}ラジアン")
# ラジアン → 度
angle_rad = math.pi/6 # π/6ラジアン
angle_deg = math.degrees(angle_rad)
print(f"{angle_rad:.3f}ラジアン = {angle_deg}度")
実行結果
30度 = 0.524ラジアン
0.524ラジアン = 30.0度
sin, cos, tanの基本的な使い方

サイン(sin)の使い方
import math
# 30度のサインを計算
angle = math.radians(30) # 30度をラジアンに変換
result = math.sin(angle)
print(f"sin(30°) = {result:.3f}") # ≒ 0.5
よく使われる角度のsin値
import math
angles = [0, 30, 45, 60, 90]
print("角度\tsin値")
print("-" * 15)
for deg in angles:
rad = math.radians(deg)
sin_val = math.sin(rad)
print(f"{deg}°\t{sin_val:.3f}")
実行結果
角度 sin値
---------------
0° 0.000
30° 0.500
45° 0.707
60° 0.866
90° 1.000
コサイン(cos)の使い方
import math
# 60度のコサインを計算
angle = math.radians(60)
result = math.cos(angle)
print(f"cos(60°) = {result:.3f}") # ≒ 0.5
cos の特徴
- cos(0°) = 1(最大値)
- cos(90°) = 0
- cos(180°) = -1(最小値)
タンジェント(tan)の使い方
import math
# 45度のタンジェントを計算
angle = math.radians(45)
result = math.tan(angle)
print(f"tan(45°) = {result:.3f}") # ≒ 1.0
tanの注意点:90度付近で無限大
import math
# 90度に近い角度での計算
angles = [89, 89.9, 89.99, 89.999]
for deg in angles:
rad = math.radians(deg)
tan_val = math.tan(rad)
print(f"tan({deg}°) = {tan_val:.2f}")
実行結果
tan(89°) = 57.29
tan(89.9°) = 572.96
tan(89.99°) = 5729.58
tan(89.999°) = 57295.78
実用例:日常で使える三角関数
例1:坂道の傾斜を計算
import math
def calc_slope(height, distance):
"""
坂道の傾斜角度を計算
height: 高さ(m)
distance: 水平距離(m)
"""
angle_rad = math.atan(height / distance) # アークタンジェント
angle_deg = math.degrees(angle_rad)
return angle_deg
# 例:高さ5m、水平距離20mの坂道
height = 5
distance = 20
slope = calc_slope(height, distance)
print(f"高さ{height}m、距離{distance}mの坂道")
print(f"傾斜角度:{slope:.1f}度")
実行結果
高さ5m、距離20mの坂道
傾斜角度:14.0度
例2:時計の針の位置を計算
import math
def clock_hand_position(hour, minute):
"""
時計の針の位置を計算(12時を0度として時計回り)
"""
# 時針の角度(30度 × 時 + 0.5度 × 分)
hour_angle = 30 * (hour % 12) + 0.5 * minute
# 分針の角度(6度 × 分)
minute_angle = 6 * minute
return hour_angle, minute_angle
# 3時15分の針の位置
hour, minute = 3, 15
h_angle, m_angle = clock_hand_position(hour, minute)
print(f"{hour}時{minute}分")
print(f"時針:{h_angle}度")
print(f"分針:{m_angle}度")
# 針の先端の座標(半径10cmの時計)
radius = 10
h_x = radius * 0.6 * math.sin(math.radians(h_angle)) # 時針は短め
h_y = radius * 0.6 * math.cos(math.radians(h_angle))
m_x = radius * math.sin(math.radians(m_angle))
m_y = radius * math.cos(math.radians(m_angle))
print(f"時針の先端座標:({h_x:.1f}, {h_y:.1f})")
print(f"分針の先端座標:({m_x:.1f}, {m_y:.1f})")
例3:ボールの放物線運動
import math
def projectile_motion(angle_deg, initial_speed, time):
"""
放物線運動の計算
angle_deg: 発射角度(度)
initial_speed: 初速度(m/s)
time: 時間(秒)
"""
angle_rad = math.radians(angle_deg)
g = 9.8 # 重力加速度
# 初速度の成分分解
vx = initial_speed * math.cos(angle_rad) # 水平成分
vy = initial_speed * math.sin(angle_rad) # 垂直成分
# 時間tでの位置
x = vx * time
y = vy * time - 0.5 * g * time**2
return x, y, vx, vy
# 45度、20m/sで発射したボールの軌道
angle = 45
speed = 20
times = [0, 0.5, 1.0, 1.5, 2.0, 2.5]
print(f"発射角度:{angle}度、初速度:{speed}m/s")
print("時間\tx位置\ty位置")
print("-" * 25)
for t in times:
x, y, vx, vy = projectile_motion(angle, speed, t)
if y >= 0: # 地面より上にある場合のみ表示
print(f"{t:.1f}s\t{x:.1f}m\t{y:.1f}m")
グラフで確認しよう【matplotlibとの連携】

sin, cos, tanの波形を描画
import math
import matplotlib.pyplot as plt
# 0度から360度までのデータを準備
degrees = list(range(0, 361)) # 0度から360度
radians = [math.radians(deg) for deg in degrees]
# 各三角関数の値を計算
sin_values = [math.sin(rad) for rad in radians]
cos_values = [math.cos(rad) for rad in radians]
# tanは90度、270度付近で発散するので別途処理
tan_values = []
for rad in radians:
try:
tan_val = math.tan(rad)
# 値が大きすぎる場合は表示しない
if abs(tan_val) > 10:
tan_values.append(float('nan'))
else:
tan_values.append(tan_val)
except:
tan_values.append(float('nan'))
# グラフを描画
plt.figure(figsize=(12, 8))
# sin波
plt.subplot(3, 1, 1)
plt.plot(degrees, sin_values, 'b-', linewidth=2, label='sin')
plt.title('サイン波(sin)')
plt.ylabel('値')
plt.grid(True, alpha=0.3)
plt.legend()
plt.ylim(-1.5, 1.5)
# cos波
plt.subplot(3, 1, 2)
plt.plot(degrees, cos_values, 'r-', linewidth=2, label='cos')
plt.title('コサイン波(cos)')
plt.ylabel('値')
plt.grid(True, alpha=0.3)
plt.legend()
plt.ylim(-1.5, 1.5)
# tan波
plt.subplot(3, 1, 3)
plt.plot(degrees, tan_values, 'g-', linewidth=2, label='tan')
plt.title('タンジェント波(tan)')
plt.xlabel('角度(度)')
plt.ylabel('値')
plt.grid(True, alpha=0.3)
plt.legend()
plt.ylim(-5, 5)
plt.tight_layout()
plt.show()
円運動のアニメーション
import math
import matplotlib.pyplot as plt
import matplotlib.animation as animation
def create_circle_animation():
"""円運動のアニメーションを作成"""
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))
# 角度のリスト(0度から360度)
angles = []
sin_values = []
cos_values = []
def animate(frame):
angle_deg = frame * 2 # 2度ずつ回転
angle_rad = math.radians(angle_deg)
# 円周上の点の座標
x = math.cos(angle_rad)
y = math.sin(angle_rad)
# データを蓄積
angles.append(angle_deg)
sin_values.append(y)
cos_values.append(x)
# 円と点を描画
ax1.clear()
ax1.set_xlim(-1.5, 1.5)
ax1.set_ylim(-1.5, 1.5)
ax1.set_aspect('equal')
# 単位円を描画
circle_angles = [math.radians(i) for i in range(361)]
circle_x = [math.cos(a) for a in circle_angles]
circle_y = [math.sin(a) for a in circle_angles]
ax1.plot(circle_x, circle_y, 'k--', alpha=0.5)
# 現在の点
ax1.plot(x, y, 'ro', markersize=10)
ax1.plot([0, x], [0, y], 'r-', linewidth=2)
ax1.set_title(f'円運動(角度: {angle_deg:.0f}度)')
ax1.grid(True, alpha=0.3)
# sin, cos波を描画
ax2.clear()
if len(angles) > 1:
ax2.plot(angles, sin_values, 'b-', label='sin', linewidth=2)
ax2.plot(angles, cos_values, 'r-', label='cos', linewidth=2)
ax2.set_xlim(0, 360)
ax2.set_ylim(-1.5, 1.5)
ax2.set_xlabel('角度(度)')
ax2.set_ylabel('値')
ax2.set_title('sin, cos波形')
ax2.grid(True, alpha=0.3)
ax2.legend()
anim = animation.FuncAnimation(fig, animate, frames=180, interval=50, repeat=True)
plt.tight_layout()
plt.show()
return anim
# アニメーションを実行
# anim = create_circle_animation()
応用例:ゲーム開発での活用
キャラクターの回転移動
import math
class Character:
def __init__(self, x, y):
self.x = x
self.y = y
self.angle = 0 # 向いている方向(度)
self.speed = 5 # 移動速度
def move_forward(self):
"""前進する"""
angle_rad = math.radians(self.angle)
self.x += self.speed * math.cos(angle_rad)
self.y += self.speed * math.sin(angle_rad)
def turn(self, angle_change):
"""向きを変える"""
self.angle += angle_change
self.angle %= 360 # 0-360度の範囲に収める
def move_to_target(self, target_x, target_y):
"""指定した座標に向かって移動"""
# 目標への方向を計算
dx = target_x - self.x
dy = target_y - self.y
# 角度を計算(atan2を使用)
target_angle = math.degrees(math.atan2(dy, dx))
# 現在の角度との差を計算
angle_diff = target_angle - self.angle
# -180度から180度の範囲に調整
if angle_diff > 180:
angle_diff -= 360
elif angle_diff < -180:
angle_diff += 360
# 少しずつ向きを変える
turn_speed = 10 # 1フレームで回転する最大角度
if abs(angle_diff) <= turn_speed:
self.angle = target_angle
else:
self.turn(turn_speed if angle_diff > 0 else -turn_speed)
# 前進
self.move_forward()
def __str__(self):
return f"位置: ({self.x:.1f}, {self.y:.1f}), 角度: {self.angle:.1f}度"
# 使用例
player = Character(0, 0)
target_x, target_y = 100, 100
print("初期状態:", player)
# 目標に向かって10ステップ移動
for step in range(10):
player.move_to_target(target_x, target_y)
print(f"ステップ{step+1}:", player)
# 目標に到達したかチェック
distance = math.sqrt((target_x - player.x)**2 + (target_y - player.y)**2)
if distance < 5: # 5ピクセル以内なら到達
print("目標に到達しました!")
break
波のような動きを作る
import math
import time
def wave_motion_demo():
"""波のような動きのデモ"""
amplitude = 5 # 振幅
frequency = 2 # 周波数
print("波のような動きのシミュレーション")
print("Ctrl+Cで終了")
try:
t = 0
while True:
# sin波で上下の動きを計算
y = amplitude * math.sin(frequency * t)
# コンソールに波を表示
spaces = int(y + amplitude + 5) # 中央揃え用
wave_str = " " * spaces + "●"
print(f"時刻{t:.1f}: {wave_str} (y={y:.1f})")
t += 0.1
time.sleep(0.1)
except KeyboardInterrupt:
print("\nシミュレーション終了")
# 実行する場合(コメントアウトを外す)
# wave_motion_demo()
よくある質問と注意点

Q1: なぜ度ではなくラジアン?
答え:数学的な定義に基づいているから
理由:
- 物理学や工学の計算でラジアンが標準
- プログラミング言語の多くがラジアンを採用
対策:
math.radians()
とmath.degrees()
を活用- よく使う角度はあらかじめ変換しておく
Q2: エラーになることはある?
よくあるエラーと対策
ZeroDivisionError(ゼロ除算エラー)
import math
# tan(90度)は理論上無限大
try:
result = math.tan(math.radians(90))
print(result) # 非常に大きな値になる
except:
print("計算できませんでした")
# 安全な書き方
angle = 90
if angle % 90 == 0 and angle % 180 != 0:
print("tan(90度)は無限大です")
else:
result = math.tan(math.radians(angle))
print(f"tan({angle}度) = {result}")
OverflowError(オーバーフローエラー)
import math
# 非常に大きな値を避ける
def safe_tan(angle_deg):
"""安全なtan計算"""
if abs(angle_deg % 180 - 90) < 0.001:
return float('inf') if (angle_deg // 90) % 2 == 1 else float('-inf')
return math.tan(math.radians(angle_deg))
# テスト
angles = [45, 89.9, 90, 90.1, 135]
for angle in angles:
result = safe_tan(angle)
print(f"tan({angle}度) = {result}")
Q3: NumPyでも使える?
はい、NumPyの方が配列処理に便利です
import numpy as np
import matplotlib.pyplot as plt
# NumPyを使った効率的な計算
angles_deg = np.arange(0, 361, 1) # 0度から360度まで1度刻み
angles_rad = np.radians(angles_deg)
# 一度に全部計算
sin_vals = np.sin(angles_rad)
cos_vals = np.cos(angles_rad)
# mathモジュールとの比較
print("NumPyの利点:")
print("- 配列全体を一度に計算")
print("- 高速処理")
print("- matplotlibとの相性が良い")
# グラフ描画
plt.figure(figsize=(10, 6))
plt.plot(angles_deg, sin_vals, label='sin', linewidth=2)
plt.plot(angles_deg, cos_vals, label='cos', linewidth=2)
plt.xlabel('角度(度)')
plt.ylabel('値')
plt.title('NumPyを使った三角関数')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
Q4: 逆三角関数も使える?
はい、asin, acos, atanが使えます
import math
# 逆三角関数の例
values = [0, 0.5, 0.707, 0.866, 1]
print("値\tasin\tacos\tatan")
print("-" * 30)
for val in values:
try:
asin_deg = math.degrees(math.asin(val))
acos_deg = math.degrees(math.acos(val))
atan_deg = math.degrees(math.atan(val))
print(f"{val}\t{asin_deg:.0f}°\t{acos_deg:.0f}°\t{atan_deg:.0f}°")
except ValueError:
print(f"{val}\t範囲外")
パフォーマンスのコツ
高速化のテクニック
事前計算の活用
import math
import time
# よく使う角度は事前に計算
COMMON_ANGLES = {
0: (0, 1, 0), # (sin, cos, tan)
30: (0.5, 0.866, 0.577),
45: (0.707, 0.707, 1),
60: (0.866, 0.5, 1.732),
90: (1, 0, float('inf'))
}
def fast_trig(angle_deg):
"""高速三角関数(事前計算済み値を使用)"""
if angle_deg in COMMON_ANGLES:
return COMMON_ANGLES[angle_deg]
else:
rad = math.radians(angle_deg)
return math.sin(rad), math.cos(rad), math.tan(rad)
# 速度比較
angles = [30, 45, 60] * 1000
start_time = time.time()
for angle in angles:
math.sin(math.radians(angle))
normal_time = time.time() - start_time
start_time = time.time()
for angle in angles:
fast_trig(angle)
fast_time = time.time() - start_time
print(f"通常の計算: {normal_time:.4f}秒")
print(f"事前計算版: {fast_time:.4f}秒")
print(f"高速化倍率: {normal_time/fast_time:.1f}倍")
まとめ
Pythonで三角関数を使いこなして、計算も可視化も自由自在!
この記事の要点
基本的な使い方
math
モジュールでsin
,cos
,tan
が使える- 単位は「度」ではなく「ラジアン」なので、変換が必要
math.radians()
とmath.degrees()
で相互変換
実用的な応用
- 物理シミュレーション(放物線運動、波動)
- ゲーム開発(キャラクター移動、回転)
- グラフ描画(波形、円運動)
- 日常計算(坂道の傾斜、時計の針)
注意点とコツ
- tan(90度)は無限大になるので注意
- NumPyを使うと配列処理が効率的
- よく使う値は事前計算で高速化
コメント