【Pythonで簡単!】三角関数(sin, cos, tan)の使い方と実用例まとめ|数学が苦手でも大丈夫!

python

三角関数の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スタート地点
30°π/6 ≒ 0.52
45°π/4 ≒ 0.794分の1
60°π/3 ≒ 1.05
90°π/2 ≒ 1.572分の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を使うと配列処理が効率的
  • よく使う値は事前計算で高速化

コメント

タイトルとURLをコピーしました