[PHP]sin関数を完全解説!サイン(正弦)を計算する方法

PHP

こんにちは!今回は、PHPの標準関数であるsin()について詳しく解説していきます。三角関数の一つで、角度のサイン(正弦)を計算する数学関数です!

sin関数とは?

sin()関数は、指定された角度のサイン(正弦)を計算する関数です。

引数はラジアン単位で指定し、-1から1の範囲の値を返します。数学、物理、グラフィックス、波形処理など、様々な分野で使用されます!

基本的な構文

sin(float $num): float
  • $num: ラジアン単位の角度
  • 戻り値: サイン値(-1.0から1.0の範囲)

基本的な使用例

シンプルな計算

// 0ラジアン(0度)のサイン
echo sin(0);  // 0

// π/2ラジアン(90度)のサイン
echo sin(M_PI / 2);  // 1

// πラジアン(180度)のサイン
echo sin(M_PI);  // 1.2246467991474E-16(ほぼ0)

// 3π/2ラジアン(270度)のサイン
echo sin(3 * M_PI / 2);  // -1

// 2πラジアン(360度)のサイン
echo sin(2 * M_PI);  // -2.4492935982947E-16(ほぼ0)

度数法からラジアンへの変換

// 度数法をラジアンに変換
function degToRad($degrees) {
    return $degrees * M_PI / 180;
}

// 30度のサイン
echo sin(degToRad(30));  // 0.5

// 45度のサイン
echo sin(degToRad(45));  // 0.70710678118655

// 60度のサイン
echo sin(degToRad(60));  // 0.86602540378444

// 90度のサイン
echo sin(degToRad(90));  // 1

deg2rad()関数を使用

// PHPの組み込み関数を使用
echo sin(deg2rad(30));  // 0.5
echo sin(deg2rad(45));  // 0.70710678118655
echo sin(deg2rad(60));  // 0.86602540378444
echo sin(deg2rad(90));  // 1

主要な角度のサイン値

// 主要な角度
$angles = [0, 30, 45, 60, 90, 120, 135, 150, 180, 270, 360];

echo "角度\tサイン値\n";
foreach ($angles as $angle) {
    $sinValue = sin(deg2rad($angle));
    echo sprintf("%d°\t%.4f\n", $angle, $sinValue);
}

/*
角度    サイン値
0°      0.0000
30°     0.5000
45°     0.7071
60°     0.8660
90°     1.0000
120°    0.8660
135°    0.7071
150°    0.5000
180°    0.0000
270°    -1.0000
360°    -0.0000
*/

実践的な使用例

例1: 三角関数計算機

class TrigCalculator {
    /**
     * サイン(度数法)
     */
    public static function sinDeg($degrees) {
        return sin(deg2rad($degrees));
    }
    
    /**
     * コサイン(度数法)
     */
    public static function cosDeg($degrees) {
        return cos(deg2rad($degrees));
    }
    
    /**
     * タンジェント(度数法)
     */
    public static function tanDeg($degrees) {
        return tan(deg2rad($degrees));
    }
    
    /**
     * すべての三角関数値を取得
     */
    public static function getAllTrig($degrees) {
        $radians = deg2rad($degrees);
        
        return [
            'angle_deg' => $degrees,
            'angle_rad' => $radians,
            'sin' => sin($radians),
            'cos' => cos($radians),
            'tan' => tan($radians)
        ];
    }
    
    /**
     * サイン値から角度を求める(アークサイン)
     */
    public static function arcsinDeg($value) {
        if ($value < -1 || $value > 1) {
            return null;
        }
        
        return rad2deg(asin($value));
    }
    
    /**
     * 三角関数の表を生成
     */
    public static function generateTable($start = 0, $end = 360, $step = 15) {
        $table = [];
        
        for ($angle = $start; $angle <= $end; $angle += $step) {
            $table[] = self::getAllTrig($angle);
        }
        
        return $table;
    }
    
    /**
     * 単位円上の座標を計算
     */
    public static function getUnitCirclePoint($degrees, $radius = 1) {
        $radians = deg2rad($degrees);
        
        return [
            'x' => $radius * cos($radians),
            'y' => $radius * sin($radians)
        ];
    }
}

// 使用例
echo "=== 三角関数計算機 ===\n";

// 特定角度の計算
$angle = 45;
echo "{$angle}度の三角関数:\n";
$trig = TrigCalculator::getAllTrig($angle);
echo "  sin: " . round($trig['sin'], 4) . "\n";
echo "  cos: " . round($trig['cos'], 4) . "\n";
echo "  tan: " . round($trig['tan'], 4) . "\n";

// アークサイン
echo "\n=== アークサイン ===\n";
$sinValue = 0.5;
$angle = TrigCalculator::arcsinDeg($sinValue);
echo "sin⁻¹({$sinValue}) = {$angle}度\n";

// 三角関数の表
echo "\n=== 三角関数表(15度刻み) ===\n";
echo "角度\tsin\t\tcos\t\ttan\n";
$table = TrigCalculator::generateTable(0, 90, 15);
foreach ($table as $row) {
    echo sprintf(
        "%d°\t%.4f\t\t%.4f\t\t%.4f\n",
        $row['angle_deg'],
        $row['sin'],
        $row['cos'],
        $row['tan']
    );
}

// 単位円上の点
echo "\n=== 単位円上の点 ===\n";
$point = TrigCalculator::getUnitCirclePoint(60);
echo "60度の位置: (" . round($point['x'], 4) . ", " . round($point['y'], 4) . ")\n";

例2: 波形生成器

class WaveGenerator {
    /**
     * サイン波を生成
     */
    public static function generateSineWave($samples, $frequency = 1, $amplitude = 1, $phase = 0) {
        $wave = [];
        
        for ($i = 0; $i < $samples; $i++) {
            $t = $i / $samples;
            $value = $amplitude * sin(2 * M_PI * $frequency * $t + $phase);
            $wave[] = $value;
        }
        
        return $wave;
    }
    
    /**
     * 複数の波を合成
     */
    public static function combineSineWaves($samples, $waves) {
        $combined = array_fill(0, $samples, 0);
        
        foreach ($waves as $wave) {
            $sineWave = self::generateSineWave(
                $samples,
                $wave['frequency'] ?? 1,
                $wave['amplitude'] ?? 1,
                $wave['phase'] ?? 0
            );
            
            for ($i = 0; $i < $samples; $i++) {
                $combined[$i] += $sineWave[$i];
            }
        }
        
        return $combined;
    }
    
    /**
     * ASCIIアートで波形を表示
     */
    public static function visualizeWave($wave, $height = 20) {
        $min = min($wave);
        $max = max($wave);
        $range = $max - $min;
        
        if ($range == 0) {
            return;
        }
        
        $output = [];
        
        foreach ($wave as $value) {
            $normalized = ($value - $min) / $range;
            $row = (int)round($normalized * ($height - 1));
            $output[] = $height - 1 - $row;
        }
        
        for ($y = 0; $y < $height; $y++) {
            $line = '';
            foreach ($output as $x => $rowIndex) {
                if ($rowIndex === $y) {
                    $line .= '*';
                } else {
                    $line .= ' ';
                }
            }
            echo $line . "\n";
        }
    }
    
    /**
     * 波形の統計情報
     */
    public static function getWaveStats($wave) {
        return [
            'min' => min($wave),
            'max' => max($wave),
            'average' => array_sum($wave) / count($wave),
            'amplitude' => (max($wave) - min($wave)) / 2,
            'samples' => count($wave)
        ];
    }
}

// 使用例
echo "=== 波形生成 ===\n";

// 単純なサイン波
$sineWave = WaveGenerator::generateSineWave(50, 1, 1, 0);

echo "サイン波(最初の10サンプル):\n";
for ($i = 0; $i < 10; $i++) {
    echo sprintf("Sample %2d: %+.4f\n", $i, $sineWave[$i]);
}

// 波形の統計
echo "\n=== 波形統計 ===\n";
$stats = WaveGenerator::getWaveStats($sineWave);
print_r($stats);

// ASCIIアート表示
echo "\n=== サイン波の可視化 ===\n";
WaveGenerator::visualizeWave($sineWave, 15);

// 複数波の合成
echo "\n=== 複数波の合成 ===\n";
$waves = [
    ['frequency' => 1, 'amplitude' => 1],
    ['frequency' => 2, 'amplitude' => 0.5],
    ['frequency' => 3, 'amplitude' => 0.3]
];

$combined = WaveGenerator::combineSineWaves(50, $waves);
WaveGenerator::visualizeWave($combined, 15);

例3: 円運動シミュレーター

class CircularMotion {
    /**
     * 円運動の位置を計算
     */
    public static function getPosition($angle, $radius, $centerX = 0, $centerY = 0) {
        $radians = deg2rad($angle);
        
        return [
            'x' => $centerX + $radius * cos($radians),
            'y' => $centerY + $radius * sin($radians),
            'angle' => $angle
        ];
    }
    
    /**
     * 円運動の軌跡を生成
     */
    public static function generateTrajectory($radius, $steps = 360, $centerX = 0, $centerY = 0) {
        $trajectory = [];
        $angleStep = 360 / $steps;
        
        for ($i = 0; $i <= $steps; $i++) {
            $angle = $i * $angleStep;
            $trajectory[] = self::getPosition($angle, $radius, $centerX, $centerY);
        }
        
        return $trajectory;
    }
    
    /**
     * 速度ベクトルを計算
     */
    public static function getVelocity($angle, $radius, $angularVelocity) {
        $radians = deg2rad($angle);
        
        // 速度 = 半径 × 角速度
        $speed = $radius * $angularVelocity;
        
        return [
            'vx' => -$speed * sin($radians),
            'vy' => $speed * cos($radians),
            'speed' => $speed
        ];
    }
    
    /**
     * リサージュ図形を生成
     */
    public static function generateLissajous($a, $b, $delta, $samples = 1000) {
        $points = [];
        
        for ($i = 0; $i <= $samples; $i++) {
            $t = $i / $samples * 2 * M_PI;
            
            $x = sin($a * $t + $delta);
            $y = sin($b * $t);
            
            $points[] = ['x' => $x, 'y' => $y];
        }
        
        return $points;
    }
    
    /**
     * 楕円運動を生成
     */
    public static function generateEllipse($radiusX, $radiusY, $steps = 360) {
        $points = [];
        $angleStep = 360 / $steps;
        
        for ($i = 0; $i <= $steps; $i++) {
            $angle = deg2rad($i * $angleStep);
            
            $points[] = [
                'x' => $radiusX * cos($angle),
                'y' => $radiusY * sin($angle)
            ];
        }
        
        return $points;
    }
}

// 使用例
echo "=== 円運動シミュレーション ===\n";

// 円上の位置
$position = CircularMotion::getPosition(45, 10);
echo "45度の位置:\n";
echo "  x: " . round($position['x'], 2) . "\n";
echo "  y: " . round($position['y'], 2) . "\n";

// 速度ベクトル
echo "\n=== 速度ベクトル ===\n";
$velocity = CircularMotion::getVelocity(45, 10, 2);
echo "45度での速度:\n";
echo "  vx: " . round($velocity['vx'], 2) . "\n";
echo "  vy: " . round($velocity['vy'], 2) . "\n";
echo "  速さ: " . round($velocity['speed'], 2) . "\n";

// 軌跡(8点のみ表示)
echo "\n=== 円運動の軌跡(8点) ===\n";
$trajectory = CircularMotion::generateTrajectory(5, 8);
foreach ($trajectory as $i => $point) {
    echo sprintf(
        "点%d: (%+.2f, %+.2f) at %d度\n",
        $i + 1,
        $point['x'],
        $point['y'],
        $point['angle']
    );
}

// 楕円運動
echo "\n=== 楕円運動(主要8点) ===\n";
$ellipse = CircularMotion::generateEllipse(10, 5, 8);
foreach ($ellipse as $i => $point) {
    echo sprintf(
        "点%d: (%+.2f, %+.2f)\n",
        $i + 1,
        $point['x'],
        $point['y']
    );
}

例4: アニメーション計算

class AnimationHelper {
    /**
     * イージング関数(サインイーズ)
     */
    public static function easeInSine($t) {
        return 1 - cos(($t * M_PI) / 2);
    }
    
    public static function easeOutSine($t) {
        return sin(($t * M_PI) / 2);
    }
    
    public static function easeInOutSine($t) {
        return -(cos(M_PI * $t) - 1) / 2;
    }
    
    /**
     * 振動アニメーション
     */
    public static function oscillate($t, $frequency = 1, $amplitude = 1) {
        return $amplitude * sin(2 * M_PI * $frequency * $t);
    }
    
    /**
     * フェードイン/アウト
     */
    public static function fade($t, $type = 'in') {
        if ($type === 'in') {
            return self::easeInSine($t);
        } else {
            return self::easeOutSine($t);
        }
    }
    
    /**
     * バウンス効果
     */
    public static function bounce($t, $bounces = 3) {
        return abs(sin($t * M_PI * $bounces));
    }
    
    /**
     * 波打つ動き
     */
    public static function wave($position, $time, $wavelength = 1, $amplitude = 1) {
        return $amplitude * sin(2 * M_PI * ($position / $wavelength - $time));
    }
    
    /**
     * アニメーションフレームを生成
     */
    public static function generateFrames($duration, $fps, $callback) {
        $frames = [];
        $totalFrames = $duration * $fps;
        
        for ($frame = 0; $frame <= $totalFrames; $frame++) {
            $t = $frame / $totalFrames;
            $frames[] = [
                'frame' => $frame,
                'time' => $t,
                'value' => $callback($t)
            ];
        }
        
        return $frames;
    }
}

// 使用例
echo "=== アニメーション計算 ===\n";

// イージング比較
echo "イージング比較(0.0から1.0まで0.25刻み):\n";
echo "t\tLinear\tEaseIn\tEaseOut\tEaseInOut\n";

for ($t = 0; $t <= 1; $t += 0.25) {
    echo sprintf(
        "%.2f\t%.4f\t%.4f\t%.4f\t%.4f\n",
        $t,
        $t,
        AnimationHelper::easeInSine($t),
        AnimationHelper::easeOutSine($t),
        AnimationHelper::easeInOutSine($t)
    );
}

// 振動アニメーション
echo "\n=== 振動アニメーション ===\n";
$frames = AnimationHelper::generateFrames(1, 10, function($t) {
    return AnimationHelper::oscillate($t, 2, 100);
});

foreach ($frames as $frame) {
    echo sprintf(
        "Frame %2d (t=%.2f): %+.2f\n",
        $frame['frame'],
        $frame['time'],
        $frame['value']
    );
}

// バウンス効果
echo "\n=== バウンス効果 ===\n";
for ($t = 0; $t <= 1; $t += 0.1) {
    $value = AnimationHelper::bounce($t, 3);
    echo sprintf("t=%.1f: %.4f\n", $t, $value);
}

例5: 物理シミュレーション

class PhysicsSimulator {
    /**
     * 単振動(バネの運動)
     */
    public static function simpleHarmonicMotion($time, $amplitude, $frequency, $phase = 0) {
        $omega = 2 * M_PI * $frequency;
        return $amplitude * sin($omega * $time + $phase);
    }
    
    /**
     * 振り子の運動
     */
    public static function pendulumMotion($time, $length, $angle0, $g = 9.8) {
        // 小角度近似
        $omega = sqrt($g / $length);
        return $angle0 * sin($omega * $time);
    }
    
    /**
     * 減衰振動
     */
    public static function dampedOscillation($time, $amplitude, $frequency, $damping) {
        return $amplitude * exp(-$damping * $time) * sin(2 * M_PI * $frequency * $time);
    }
    
    /**
     * 投射運動の軌跡
     */
    public static function projectileMotion($velocity, $angle, $time, $g = 9.8) {
        $radians = deg2rad($angle);
        
        $vx = $velocity * cos($radians);
        $vy = $velocity * sin($radians);
        
        return [
            'x' => $vx * $time,
            'y' => $vy * $time - 0.5 * $g * $time * $time,
            'vx' => $vx,
            'vy' => $vy - $g * $time
        ];
    }
    
    /**
     * 波の干渉
     */
    public static function waveInterference($x, $t, $sources) {
        $amplitude = 0;
        
        foreach ($sources as $source) {
            $distance = abs($x - $source['position']);
            $phase = 2 * M_PI * ($source['frequency'] * $t - $distance / $source['wavelength']);
            $amplitude += $source['amplitude'] * sin($phase);
        }
        
        return $amplitude;
    }
}

// 使用例
echo "=== 物理シミュレーション ===\n";

// 単振動
echo "単振動(振幅10、周波数1Hz):\n";
for ($t = 0; $t <= 1; $t += 0.1) {
    $position = PhysicsSimulator::simpleHarmonicMotion($t, 10, 1);
    echo sprintf("t=%.1fs: 位置=%.2fcm\n", $t, $position);
}

// 振り子
echo "\n=== 振り子運動 ===\n";
echo "長さ1m、初期角度30度:\n";
for ($t = 0; $t <= 2; $t += 0.2) {
    $angle = PhysicsSimulator::pendulumMotion($t, 1, deg2rad(30));
    echo sprintf("t=%.1fs: 角度=%.2f度\n", $t, rad2deg($angle));
}

// 投射運動
echo "\n=== 投射運動 ===\n";
echo "初速20m/s、角度45度:\n";
for ($t = 0; $t <= 2; $t += 0.5) {
    $pos = PhysicsSimulator::projectileMotion(20, 45, $t);
    if ($pos['y'] >= 0) {
        echo sprintf(
            "t=%.1fs: x=%.2fm, y=%.2fm\n",
            $t,
            $pos['x'],
            $pos['y']
        );
    }
}

// 減衰振動
echo "\n=== 減衰振動 ===\n";
echo "振幅10、周波数1Hz、減衰係数0.5:\n";
for ($t = 0; $t <= 3; $t += 0.5) {
    $amplitude = PhysicsSimulator::dampedOscillation($t, 10, 1, 0.5);
    echo sprintf("t=%.1fs: 振幅=%.2f\n", $t, $amplitude);
}

例6: SVGグラフ生成

class SVGGraphGenerator {
    /**
     * サイン波のSVGを生成
     */
    public static function generateSineWaveSVG($width = 800, $height = 400, $periods = 2) {
        $svg = "<svg width='{$width}' height='{$height}' xmlns='http://www.w3.org/2000/svg'>\n";
        
        // 背景
        $svg .= "<rect width='{$width}' height='{$height}' fill='white' stroke='black'/>\n";
        
        // 中心線
        $centerY = $height / 2;
        $svg .= "<line x1='0' y1='{$centerY}' x2='{$width}' y2='{$centerY}' stroke='gray' stroke-dasharray='5,5'/>\n";
        
        // サイン波
        $points = [];
        $amplitude = $height / 2 * 0.8;
        
        for ($x = 0; $x <= $width; $x++) {
            $t = ($x / $width) * $periods * 2 * M_PI;
            $y = $centerY - $amplitude * sin($t);
            $points[] = "{$x},{$y}";
        }
        
        $pathData = "M " . implode(" L ", $points);
        $svg .= "<path d='{$pathData}' fill='none' stroke='blue' stroke-width='2'/>\n";
        
        $svg .= "</svg>";
        
        return $svg;
    }
    
    /**
     * 複数の波を重ねたSVGを生成
     */
    public static function generateMultiWaveSVG($width = 800, $height = 400) {
        $svg = "<svg width='{$width}' height='{$height}' xmlns='http://www.w3.org/2000/svg'>\n";
        $svg .= "<rect width='{$width}' height='{$height}' fill='white' stroke='black'/>\n";
        
        $centerY = $height / 2;
        $colors = ['red', 'blue', 'green'];
        $frequencies = [1, 2, 3];
        
        foreach ($frequencies as $i => $freq) {
            $points = [];
            $amplitude = $height / 2 * 0.3;
            
            for ($x = 0; $x <= $width; $x++) {
                $t = ($x / $width) * 2 * M_PI;
                $y = $centerY - $amplitude * sin($freq * $t);
                $points[] = "{$x},{$y}";
            }
            
            $pathData = "M " . implode(" L ", $points);
            $svg .= "<path d='{$pathData}' fill='none' stroke='{$colors[$i]}' stroke-width='2'/>\n";
        }
        
        $svg .= "</svg>";
        
        return $svg;
    }
}

// 使用例
echo "=== SVGグラフ生成 ===\n";

$svgSine = SVGGraphGenerator::generateSineWaveSVG();
file_put_contents('/tmp/sine_wave.svg', $svgSine);
echo "サイン波SVGを生成: /tmp/sine_wave.svg\n";

$svgMulti = SVGGraphGenerator::generateMultiWaveSVG();
file_put_contents('/tmp/multi_wave.svg', $svgMulti);
echo "複数波SVGを生成: /tmp/multi_wave.svg\n";

関連する三角関数

$angle = deg2rad(45);

// サイン
echo "sin(45°) = " . sin($angle) . "\n";

// コサイン
echo "cos(45°) = " . cos($angle) . "\n";

// タンジェント
echo "tan(45°) = " . tan($angle) . "\n";

// 逆三角関数
echo "asin(0.5) = " . rad2deg(asin(0.5)) . "°\n";
echo "acos(0.5) = " . rad2deg(acos(0.5)) . "°\n";
echo "atan(1) = " . rad2deg(atan(1)) . "°\n";

まとめ

sin()関数の特徴をまとめると:

できること:

  • サイン(正弦)の計算
  • 波形生成
  • 円運動・振動の計算
  • アニメーション

引数と戻り値:

  • 引数: ラジアン単位の角度
  • 戻り値: -1.0から1.0の範囲

推奨される使用場面:

  • 数学計算
  • 物理シミュレーション
  • グラフィックス
  • 波形処理
  • アニメーション
  • ゲーム開発

重要な定数:

  • M_PI: 円周率π(約3.14159)
  • M_PI_2: π/2
  • M_PI_4: π/4

単位変換:

// 度→ラジアン
$rad = deg2rad($deg);

// ラジアン→度
$deg = rad2deg($rad);

関連関数:

  • cos(): コサイン
  • tan(): タンジェント
  • asin(): アークサイン
  • sinh(): 双曲線サイン
  • deg2rad(): 度をラジアンに変換
  • rad2deg(): ラジアンを度に変換

よく使うパターン:

// 単位円上の点
$x = cos($angle);
$y = sin($angle);

// サイン波
$value = $amplitude * sin($frequency * $time);

// イージング
$eased = sin(($t * M_PI) / 2);

sin()は、数学や物理計算の基本となる重要な関数です。グラフィックス、アニメーション、シミュレーションなど、様々な場面で活躍します!

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