[PHP]sinh関数を完全解説!双曲線サイン(ハイパボリックサイン)を計算する方法

PHP

こんにちは!今回は、PHPの標準関数であるsinh()について詳しく解説していきます。双曲線サイン(ハイパボリックサイン)を計算する数学関数です!

sinh関数とは?

sinh()関数は、指定された値の双曲線サイン(ハイパボリックサイン)を計算する関数です。

双曲線関数の一つで、sinh(x) = (e^x - e^-x) / 2という式で定義されます。物理学、工学、統計学など、様々な分野で使用されます!

基本的な構文

sinh(float $num): float
  • $num: 双曲線サインを計算する値
  • 戻り値: 双曲線サイン値

定義と数学的背景

// sinh(x)の定義
function sinh_manual($x) {
    return (exp($x) - exp(-$x)) / 2;
}

// 組み込み関数と比較
$x = 2;
echo "sinh({$x}) = " . sinh($x) . "\n";
echo "手動計算 = " . sinh_manual($x) . "\n";
// 両方とも同じ結果

/*
sinh(x) = (e^x - e^-x) / 2

主な性質:
- sinh(0) = 0
- sinh(-x) = -sinh(x) (奇関数)
- sinh(x)は単調増加
- lim(x→∞) sinh(x) = ∞
- lim(x→-∞) sinh(x) = -∞
*/

基本的な使用例

シンプルな計算

// 基本的な値
echo sinh(0);     // 0
echo sinh(1);     // 1.1752011936438
echo sinh(-1);    // -1.1752011936438
echo sinh(2);     // 3.6268604078471
echo sinh(-2);    // -3.6268604078471

// 大きな値
echo sinh(5);     // 74.203210577788
echo sinh(10);    // 11013.232874703

// 小さな値
echo sinh(0.1);   // 0.10016675001984
echo sinh(0.01);  // 0.010000166667417

主要な値の計算

echo "=== 双曲線サインの主要な値 ===\n";

$values = [-3, -2, -1, 0, 1, 2, 3];

foreach ($values as $x) {
    echo sprintf("sinh(%+d) = %+.6f\n", $x, sinh($x));
}

/*
sinh(-3) = -10.017875
sinh(-2) = -3.626860
sinh(-1) = -1.175201
sinh(+0) = +0.000000
sinh(+1) = +1.175201
sinh(+2) = +3.626860
sinh(+3) = +10.017875
*/

双曲線恒等式の確認

// cosh²(x) - sinh²(x) = 1
$x = 2;
$cosh_squared = pow(cosh($x), 2);
$sinh_squared = pow(sinh($x), 2);

echo "cosh²({$x}) - sinh²({$x}) = " . ($cosh_squared - $sinh_squared) . "\n";
// 結果: 1(許容誤差内)

// sinh(2x) = 2·sinh(x)·cosh(x)
$sinh_2x = sinh(2 * $x);
$two_sinh_cosh = 2 * sinh($x) * cosh($x);

echo "sinh(2×{$x}) = " . $sinh_2x . "\n";
echo "2·sinh({$x})·cosh({$x}) = " . $two_sinh_cosh . "\n";
// 両方とも同じ値

実践的な使用例

例1: 双曲線関数計算機

class HyperbolicCalculator {
    /**
     * 双曲線サイン
     */
    public static function sinh($x) {
        return sinh($x);
    }
    
    /**
     * 双曲線コサイン
     */
    public static function cosh($x) {
        return cosh($x);
    }
    
    /**
     * 双曲線タンジェント
     */
    public static function tanh($x) {
        return tanh($x);
    }
    
    /**
     * 逆双曲線サイン
     */
    public static function asinh($x) {
        return asinh($x);
    }
    
    /**
     * 逆双曲線コサイン
     */
    public static function acosh($x) {
        if ($x < 1) {
            return null;
        }
        return acosh($x);
    }
    
    /**
     * 逆双曲線タンジェント
     */
    public static function atanh($x) {
        if (abs($x) >= 1) {
            return null;
        }
        return atanh($x);
    }
    
    /**
     * すべての双曲線関数値を取得
     */
    public static function getAllHyperbolic($x) {
        return [
            'x' => $x,
            'sinh' => sinh($x),
            'cosh' => cosh($x),
            'tanh' => tanh($x),
            'csch' => 1 / sinh($x),  // 双曲線余割
            'sech' => 1 / cosh($x),  // 双曲線正割
            'coth' => cosh($x) / sinh($x)  // 双曲線余接
        ];
    }
    
    /**
     * 双曲線関数の表を生成
     */
    public static function generateTable($start = -3, $end = 3, $step = 0.5) {
        $table = [];
        
        for ($x = $start; $x <= $end; $x += $step) {
            if ($x == 0) {
                // sinh(0) = 0なので除算を避ける
                $table[] = [
                    'x' => $x,
                    'sinh' => sinh($x),
                    'cosh' => cosh($x),
                    'tanh' => tanh($x)
                ];
            } else {
                $table[] = self::getAllHyperbolic($x);
            }
        }
        
        return $table;
    }
    
    /**
     * グーデルマン関数(双曲線関数と三角関数の関係)
     */
    public static function gudermannian($x) {
        return 2 * atan(tanh($x / 2));
    }
}

// 使用例
echo "=== 双曲線関数計算機 ===\n";

$x = 1.5;
echo "x = {$x}の双曲線関数:\n";
$hyp = HyperbolicCalculator::getAllHyperbolic($x);

foreach ($hyp as $name => $value) {
    if ($name !== 'x') {
        echo sprintf("  %s: %.6f\n", $name, $value);
    }
}

// 逆関数
echo "\n=== 逆双曲線関数 ===\n";
$value = 2;
echo "asinh({$value}) = " . HyperbolicCalculator::asinh($value) . "\n";
echo "acosh({$value}) = " . HyperbolicCalculator::acosh($value) . "\n";

$value = 0.5;
echo "atanh({$value}) = " . HyperbolicCalculator::atanh($value) . "\n";

// 双曲線関数表
echo "\n=== 双曲線関数表 ===\n";
echo "x\tsinh(x)\t\tcosh(x)\t\ttanh(x)\n";

$table = HyperbolicCalculator::generateTable(-2, 2, 1);
foreach ($table as $row) {
    echo sprintf(
        "%.1f\t%.6f\t%.6f\t%.6f\n",
        $row['x'],
        $row['sinh'],
        $row['cosh'],
        $row['tanh']
    );
}

例2: 懸垂線(カテナリー)の計算

class Catenary {
    /**
     * 懸垂線の形状を計算
     * y = a * cosh(x/a)
     */
    public static function calculate($x, $a = 1) {
        return $a * cosh($x / $a);
    }
    
    /**
     * 懸垂線の長さを計算
     */
    public static function arcLength($x, $a = 1) {
        return $a * sinh($x / $a);
    }
    
    /**
     * 懸垂線の曲線を生成
     */
    public static function generateCurve($start, $end, $steps, $a = 1) {
        $curve = [];
        $step = ($end - $start) / $steps;
        
        for ($i = 0; $i <= $steps; $i++) {
            $x = $start + $i * $step;
            $y = self::calculate($x, $a);
            
            $curve[] = [
                'x' => $x,
                'y' => $y
            ];
        }
        
        return $curve;
    }
    
    /**
     * 電線や橋のケーブルの垂れ下がりを計算
     */
    public static function cableSag($span, $tension, $weight) {
        // a = 張力 / 単位重量
        $a = $tension / $weight;
        
        // 最低点からの高さ
        $halfSpan = $span / 2;
        $sag = $a * (cosh($halfSpan / $a) - 1);
        
        return [
            'sag' => $sag,
            'parameter' => $a,
            'span' => $span
        ];
    }
    
    /**
     * 懸垂線の面積を計算
     */
    public static function area($x1, $x2, $a = 1) {
        // 懸垂線とx軸の間の面積
        return $a * $a * (sinh($x2 / $a) - sinh($x1 / $a));
    }
}

// 使用例
echo "=== 懸垂線(カテナリー) ===\n";

// 基本的な懸垂線
$a = 10;
echo "パラメータa={$a}の懸垂線:\n";

$curve = Catenary::generateCurve(-20, 20, 8, $a);
foreach ($curve as $point) {
    echo sprintf("x=%+.1f: y=%.2f\n", $point['x'], $point['y']);
}

// ケーブルの垂れ下がり
echo "\n=== ケーブルの垂れ下がり ===\n";
$span = 100;  // スパン(m)
$tension = 5000;  // 張力(N)
$weight = 50;  // 単位重量(N/m)

$sag = Catenary::cableSag($span, $tension, $weight);
echo "スパン: {$sag['span']}m\n";
echo "垂れ下がり: " . round($sag['sag'], 2) . "m\n";

// 弧長
echo "\n=== 懸垂線の長さ ===\n";
$x = 10;
$arcLength = Catenary::arcLength($x, $a);
echo "x=0から{$x}までの弧長: " . round($arcLength, 2) . "\n";

例3: 統計学での応用

class StatisticsHelper {
    /**
     * ロジスティック関数(シグモイド関数)
     */
    public static function sigmoid($x) {
        return 1 / (1 + exp(-$x));
    }
    
    /**
     * ソフトマックス関数
     */
    public static function softmax($values) {
        $expValues = array_map('exp', $values);
        $sum = array_sum($expValues);
        
        return array_map(function($val) use ($sum) {
            return $val / $sum;
        }, $expValues);
    }
    
    /**
     * 双曲線正接を使った正規化
     */
    public static function tanhNormalization($x, $scale = 1) {
        return tanh($x / $scale);
    }
    
    /**
     * フィッシャー変換(相関係数の変換)
     */
    public static function fisherTransform($r) {
        if (abs($r) >= 1) {
            return null;
        }
        
        return 0.5 * log((1 + $r) / (1 - $r));
        // これはatanh(r)と同じ
    }
    
    /**
     * 逆フィッシャー変換
     */
    public static function inverseFisherTransform($z) {
        return tanh($z);
    }
    
    /**
     * グンベル分布の確率密度関数
     */
    public static function gumbelPDF($x, $mu = 0, $beta = 1) {
        $z = ($x - $mu) / $beta;
        return (1 / $beta) * exp(-($z + exp(-$z)));
    }
}

// 使用例
echo "=== 統計学での応用 ===\n";

// シグモイド関数
echo "シグモイド関数:\n";
$values = [-3, -2, -1, 0, 1, 2, 3];
foreach ($values as $x) {
    echo sprintf("sigmoid(%+d) = %.4f\n", $x, StatisticsHelper::sigmoid($x));
}

// tanhによる正規化
echo "\n=== tanh正規化 ===\n";
$data = [10, 20, 30, 40, 50];
foreach ($data as $x) {
    $normalized = StatisticsHelper::tanhNormalization($x, 50);
    echo sprintf("%d → %.4f\n", $x, $normalized);
}

// フィッシャー変換
echo "\n=== フィッシャー変換 ===\n";
$correlations = [0.3, 0.5, 0.7, 0.9];
foreach ($correlations as $r) {
    $z = StatisticsHelper::fisherTransform($r);
    $r_back = StatisticsHelper::inverseFisherTransform($z);
    echo sprintf("r=%.1f → z=%.4f → r=%.4f\n", $r, $z, $r_back);
}

// ソフトマックス
echo "\n=== ソフトマックス関数 ===\n";
$logits = [2.0, 1.0, 0.1];
$probabilities = StatisticsHelper::softmax($logits);
echo "入力: " . implode(', ', $logits) . "\n";
echo "確率: " . implode(', ', array_map(fn($p) => round($p, 4), $probabilities)) . "\n";
echo "合計: " . round(array_sum($probabilities), 4) . "\n";

例4: 物理学での応用

class PhysicsApplications {
    /**
     * 相対論的速度の加算
     */
    public static function relativisticVelocityAddition($v1, $v2, $c = 299792458) {
        // v = (v1 + v2) / (1 + v1*v2/c²)
        return ($v1 + $v2) / (1 + ($v1 * $v2) / ($c * $c));
    }
    
    /**
     * ラピディティ(相対論的速度パラメータ)
     */
    public static function rapidity($velocity, $c = 299792458) {
        $beta = $velocity / $c;
        
        if (abs($beta) >= 1) {
            return null;
        }
        
        return atanh($beta);
    }
    
    /**
     * ローレンツ因子
     */
    public static function lorentzFactor($velocity, $c = 299792458) {
        $beta = $velocity / $c;
        return 1 / sqrt(1 - $beta * $beta);
    }
    
    /**
     * 懸垂線形状の重力ポテンシャル
     */
    public static function catenaryPotential($x, $a, $g = 9.8, $rho = 1) {
        // 単位長さあたりのポテンシャルエネルギー
        $y = $a * cosh($x / $a);
        return $rho * $g * $y;
    }
    
    /**
     * 双曲線軌道(宇宙船の軌道)
     */
    public static function hyperbolicOrbit($theta, $a, $e) {
        // e > 1 の場合の双曲線軌道
        if ($e <= 1) {
            return null;
        }
        
        $r = $a * (1 - $e * $e) / (1 + $e * cos($theta));
        return $r;
    }
}

// 使用例
echo "=== 物理学での応用 ===\n";

// 相対論的速度
echo "相対論的速度の加算:\n";
$c = 299792458;  // 光速 m/s
$v1 = 0.6 * $c;
$v2 = 0.6 * $c;

$v_classical = $v1 + $v2;
$v_relativistic = PhysicsApplications::relativisticVelocityAddition($v1, $v2, $c);

echo "古典的: " . ($v_classical / $c) . "c\n";
echo "相対論的: " . ($v_relativistic / $c) . "c\n";

// ラピディティ
echo "\n=== ラピディティ ===\n";
$velocities = [0.1, 0.3, 0.5, 0.7, 0.9];
foreach ($velocities as $beta) {
    $v = $beta * $c;
    $rapidity = PhysicsApplications::rapidity($v, $c);
    $gamma = PhysicsApplications::lorentzFactor($v, $c);
    
    echo sprintf(
        "v=%.1fc: ラピディティ=%.4f, γ=%.4f\n",
        $beta,
        $rapidity,
        $gamma
    );
}

// 懸垂線のポテンシャル
echo "\n=== 懸垂線のポテンシャルエネルギー ===\n";
$a = 10;
$positions = [-10, -5, 0, 5, 10];
foreach ($positions as $x) {
    $potential = PhysicsApplications::catenaryPotential($x, $a);
    echo sprintf("x=%+d: U=%.2f J/m\n", $x, $potential);
}

例5: 工学での応用

class EngineeringApplications {
    /**
     * 送電線の垂れ下がり計算
     */
    public static function powerLineSag($span, $weight, $tension) {
        $a = $tension / $weight;
        $halfSpan = $span / 2;
        
        return [
            'sag' => $a * (cosh($halfSpan / $a) - 1),
            'cable_length' => 2 * $a * sinh($halfSpan / $a),
            'max_tension' => $weight * $a * cosh($halfSpan / $a)
        ];
    }
    
    /**
     * 熱交換器の温度分布
     */
    public static function heatExchangerTemperature($x, $L, $T1, $T2) {
        // 双曲線関数を使った温度分布モデル
        return $T1 + ($T2 - $T1) * (sinh($x / $L) / sinh(1));
    }
    
    /**
     * ビーム(梁)のたわみ
     */
    public static function beamDeflection($x, $L, $load, $EI) {
        // 双曲線関数を使った梁のたわみ計算
        $lambda = sqrt($load / $EI);
        return (1 / ($lambda * $lambda * $EI)) * 
               (cosh($lambda * $x) - 1 - $lambda * $x * sinh($lambda * $L) / sinh($lambda * $L));
    }
    
    /**
     * 圧力容器の応力分布
     */
    public static function pressureVesselStress($r, $r_inner, $r_outer, $pressure) {
        // 双曲線関数を使った応力計算
        $k = $r_outer / $r_inner;
        $radial_stress = -$pressure * (($k * $k - ($r / $r_inner) ** 2) / ($k * $k - 1));
        
        return $radial_stress;
    }
}

// 使用例
echo "=== 工学での応用 ===\n";

// 送電線
echo "送電線の計算:\n";
$span = 200;  // m
$weight = 15;  // N/m
$tension = 30000;  // N

$result = EngineeringApplications::powerLineSag($span, $weight, $tension);
echo "スパン: {$span}m\n";
echo "垂れ下がり: " . round($result['sag'], 2) . "m\n";
echo "ケーブル長: " . round($result['cable_length'], 2) . "m\n";
echo "最大張力: " . round($result['max_tension'], 2) . "N\n";

// 熱交換器
echo "\n=== 熱交換器の温度分布 ===\n";
$L = 1.0;
$T1 = 20;  // 入口温度
$T2 = 80;  // 出口温度

for ($x = 0; $x <= $L; $x += 0.2) {
    $T = EngineeringApplications::heatExchangerTemperature($x, $L, $T1, $T2);
    echo sprintf("x=%.1fm: T=%.1f°C\n", $x, $T);
}

例6: 数値計算とシミュレーション

class NumericalMethods {
    /**
     * 双曲線関数を使った微分方程式の解
     */
    public static function hyperbolicODE($x, $A, $B, $lambda) {
        return $A * cosh($lambda * $x) + $B * sinh($lambda * $x);
    }
    
    /**
     * グッゲンハイム法(指数関数のフィッティング)
     */
    public static function guggenheimFit($data) {
        // 双曲線関数を使ったカーブフィッティング
        $n = count($data);
        $sum_x = 0;
        $sum_y = 0;
        
        foreach ($data as $point) {
            $sum_x += $point['x'];
            $sum_y += log(abs($point['y']));
        }
        
        $mean_x = $sum_x / $n;
        $mean_y = $sum_y / $n;
        
        return [
            'a' => exp($mean_y),
            'b' => $mean_x
        ];
    }
    
    /**
     * 双曲線補間
     */
    public static function hyperbolicInterpolation($x, $x0, $x1, $y0, $y1) {
        $t = ($x - $x0) / ($x1 - $x0);
        
        // 双曲線正接を使った補間
        $s = (tanh(2 * $t - 1) + 1) / 2;
        
        return $y0 + $s * ($y1 - $y0);
    }
}

// 使用例
echo "=== 数値計算 ===\n";

// 微分方程式の解
echo "双曲線関数による微分方程式の解:\n";
$A = 1;
$B = 2;
$lambda = 0.5;

for ($x = -2; $x <= 2; $x += 1) {
    $y = NumericalMethods::hyperbolicODE($x, $A, $B, $lambda);
    echo sprintf("x=%+d: y=%.4f\n", $x, $y);
}

// 双曲線補間
echo "\n=== 双曲線補間 ===\n";
$x0 = 0;
$x1 = 10;
$y0 = 0;
$y1 = 100;

for ($x = 0; $x <= 10; $x += 2) {
    $y = NumericalMethods::hyperbolicInterpolation($x, $x0, $x1, $y0, $y1);
    echo sprintf("x=%d: y=%.2f\n", $x, $y);
}

関連する双曲線関数

$x = 1.5;

echo "=== 双曲線関数ファミリー ===\n";

// 双曲線サイン
echo "sinh({$x}) = " . sinh($x) . "\n";

// 双曲線コサイン
echo "cosh({$x}) = " . cosh($x) . "\n";

// 双曲線タンジェント
echo "tanh({$x}) = " . tanh($x) . "\n";

// 逆双曲線関数
echo "\n=== 逆双曲線関数 ===\n";
$y = 2;
echo "asinh({$y}) = " . asinh($y) . "\n";
echo "acosh({$y}) = " . acosh($y) . "\n";

$y = 0.5;
echo "atanh({$y}) = " . atanh($y) . "\n";

まとめ

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

できること:

  • 双曲線サインの計算
  • 懸垂線の形状計算
  • 相対論的計算
  • 統計学での変換

定義:

sinh(x) = (e^x - e^-x) / 2

性質:

  • 奇関数: sinh(-x) = -sinh(x)
  • sinh(0) = 0
  • 単調増加関数
  • 値域: (-∞, +∞)

推奨される使用場面:

  • 懸垂線(カテナリー)の計算
  • 相対論的物理学
  • 統計学(フィッシャー変換)
  • 工学(送電線、梁のたわみ)
  • 数値計算

重要な恒等式:

cosh²(x) - sinh²(x) = 1
sinh(2x) = 2·sinh(x)·cosh(x)
cosh(x) + sinh(x) = e^x
cosh(x) - sinh(x) = e^-x

関連関数:

  • cosh(): 双曲線コサイン
  • tanh(): 双曲線タンジェント
  • asinh(): 逆双曲線サイン
  • acosh(): 逆双曲線コサイン
  • atanh(): 逆双曲線タンジェント
  • exp(): 指数関数

よく使うパターン:

// 懸垂線
$y = $a * cosh($x / $a);

// 双曲線軌道
$r = $a * (e² - 1) / (1 + e * cos($theta));

// tanh正規化
$normalized = tanh($x / $scale);

sinh()は、物理学、工学、統計学など様々な分野で重要な役割を果たす関数です。特に懸垂線や相対論的計算では欠かせない関数です!

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