[PHP]sqrt関数を完全解説!平方根(ルート)を計算する方法

PHP

こんにちは!今回は、PHPの標準関数であるsqrt()について詳しく解説していきます。数値の平方根(ルート)を計算する、最も基本的な数学関数の一つです!

sqrt関数とは?

sqrt()関数は、指定された数値の平方根(√)を計算する関数です。

“square root”の略で、ある数を2乗するとその値になる数を求めます。数学、物理、統計、幾何学など、あらゆる分野で使用される基本的な計算です!

基本的な構文

sqrt(float $num): float
  • $num: 平方根を求める数値(0以上)
  • 戻り値: 平方根の値、負の数の場合はNAN

基本的な使用例

シンプルな計算

// 完全平方数
echo sqrt(4);      // 2
echo sqrt(9);      // 3
echo sqrt(16);     // 4
echo sqrt(25);     // 5
echo sqrt(100);    // 10

// 完全平方数でない場合
echo sqrt(2);      // 1.4142135623731
echo sqrt(3);      // 1.7320508075689
echo sqrt(5);      // 2.2360679774998

// 小数
echo sqrt(0.25);   // 0.5
echo sqrt(1.44);   // 1.2

// 0と1
echo sqrt(0);      // 0
echo sqrt(1);      // 1

負の数の扱い

// 負の数
$result = sqrt(-1);
echo $result;      // NAN(Not A Number)

// NANのチェック
if (is_nan($result)) {
    echo "負の数の平方根は実数では定義されません\n";
}

// 安全な計算
function safeSqrt($num) {
    if ($num < 0) {
        return null;
    }
    return sqrt($num);
}

echo safeSqrt(9);     // 3
echo safeSqrt(-9);    // null

検証(平方根の確認)

$num = 25;
$root = sqrt($num);

echo "√{$num} = {$root}\n";
echo "{$root}² = " . pow($root, 2) . "\n";
// √25 = 5
// 5² = 25

// 浮動小数点の誤差
$num = 2;
$root = sqrt($num);
$squared = $root * $root;

echo "√{$num} = {$root}\n";
echo "{$root}² = {$squared}\n";
// わずかな誤差が生じる可能性がある

実践的な使用例

例1: 幾何学計算機

class GeometryCalculator {
    /**
     * 三平方の定理(斜辺の長さ)
     */
    public static function pythagorean($a, $b) {
        return sqrt($a * $a + $b * $b);
    }
    
    /**
     * 2点間の距離(2D)
     */
    public static function distance2D($x1, $y1, $x2, $y2) {
        $dx = $x2 - $x1;
        $dy = $y2 - $y1;
        
        return sqrt($dx * $dx + $dy * $dy);
    }
    
    /**
     * 2点間の距離(3D)
     */
    public static function distance3D($x1, $y1, $z1, $x2, $y2, $z2) {
        $dx = $x2 - $x1;
        $dy = $y2 - $y1;
        $dz = $z2 - $z1;
        
        return sqrt($dx * $dx + $dy * $dy + $dz * $dz);
    }
    
    /**
     * 円の半径から面積
     */
    public static function circleRadiusFromArea($area) {
        return sqrt($area / M_PI);
    }
    
    /**
     * 正方形の一辺の長さから対角線の長さ
     */
    public static function squareDiagonal($side) {
        return $side * sqrt(2);
    }
    
    /**
     * 球の体積から半径
     */
    public static function sphereRadiusFromVolume($volume) {
        return pow((3 * $volume) / (4 * M_PI), 1/3);
    }
    
    /**
     * ベクトルの大きさ(ノルム)
     */
    public static function vectorMagnitude($components) {
        $sumSquares = 0;
        
        foreach ($components as $component) {
            $sumSquares += $component * $component;
        }
        
        return sqrt($sumSquares);
    }
    
    /**
     * 楕円の周長の近似値(ラマヌジャンの公式)
     */
    public static function ellipsePerimeter($a, $b) {
        $h = pow($a - $b, 2) / pow($a + $b, 2);
        return M_PI * ($a + $b) * (1 + (3 * $h) / (10 + sqrt(4 - 3 * $h)));
    }
}

// 使用例
echo "=== 幾何学計算 ===\n";

// 三平方の定理
$a = 3;
$b = 4;
$c = GeometryCalculator::pythagorean($a, $b);
echo "直角三角形({$a}, {$b})の斜辺: {$c}\n";
// 3² + 4² = 5²

// 2点間の距離
$point1 = [0, 0];
$point2 = [3, 4];
$distance = GeometryCalculator::distance2D(...$point1, ...$point2);
echo "点({$point1[0]}, {$point1[1]})と点({$point2[0]}, {$point2[1]})の距離: {$distance}\n";

// 3D距離
$point1_3d = [0, 0, 0];
$point2_3d = [1, 2, 2];
$distance_3d = GeometryCalculator::distance3D(...$point1_3d, ...$point2_3d);
echo "3D距離: " . round($distance_3d, 2) . "\n";

// 正方形の対角線
$side = 5;
$diagonal = GeometryCalculator::squareDiagonal($side);
echo "一辺{$side}の正方形の対角線: " . round($diagonal, 2) . "\n";

// ベクトルの大きさ
$vector = [3, 4, 12];
$magnitude = GeometryCalculator::vectorMagnitude($vector);
echo "ベクトル[" . implode(', ', $vector) . "]の大きさ: {$magnitude}\n";

// 円の半径
$area = 78.5;
$radius = GeometryCalculator::circleRadiusFromArea($area);
echo "面積{$area}の円の半径: " . round($radius, 2) . "\n";

例2: 統計計算

class Statistics {
    /**
     * 標準偏差
     */
    public static function standardDeviation($values) {
        $count = count($values);
        
        if ($count === 0) {
            return 0;
        }
        
        $mean = array_sum($values) / $count;
        
        $variance = 0;
        foreach ($values as $value) {
            $variance += pow($value - $mean, 2);
        }
        $variance /= $count;
        
        return sqrt($variance);
    }
    
    /**
     * 標本標準偏差
     */
    public static function sampleStandardDeviation($values) {
        $count = count($values);
        
        if ($count <= 1) {
            return 0;
        }
        
        $mean = array_sum($values) / $count;
        
        $variance = 0;
        foreach ($values as $value) {
            $variance += pow($value - $mean, 2);
        }
        $variance /= ($count - 1);  // n-1で割る
        
        return sqrt($variance);
    }
    
    /**
     * 二乗平均平方根(RMS)
     */
    public static function rms($values) {
        $count = count($values);
        
        if ($count === 0) {
            return 0;
        }
        
        $sumSquares = 0;
        foreach ($values as $value) {
            $sumSquares += $value * $value;
        }
        
        return sqrt($sumSquares / $count);
    }
    
    /**
     * 幾何平均
     */
    public static function geometricMean($values) {
        $count = count($values);
        
        if ($count === 0) {
            return 0;
        }
        
        $product = 1;
        foreach ($values as $value) {
            if ($value <= 0) {
                return null;  // 負の値や0は計算できない
            }
            $product *= $value;
        }
        
        return pow($product, 1 / $count);
    }
    
    /**
     * ユークリッドノルム(L2ノルム)
     */
    public static function euclideanNorm($values) {
        $sumSquares = 0;
        
        foreach ($values as $value) {
            $sumSquares += $value * $value;
        }
        
        return sqrt($sumSquares);
    }
    
    /**
     * 相関係数
     */
    public static function correlation($x, $y) {
        $n = count($x);
        
        if ($n !== count($y) || $n === 0) {
            return null;
        }
        
        $meanX = array_sum($x) / $n;
        $meanY = array_sum($y) / $n;
        
        $covariance = 0;
        $varianceX = 0;
        $varianceY = 0;
        
        for ($i = 0; $i < $n; $i++) {
            $dx = $x[$i] - $meanX;
            $dy = $y[$i] - $meanY;
            
            $covariance += $dx * $dy;
            $varianceX += $dx * $dx;
            $varianceY += $dy * $dy;
        }
        
        $denominator = sqrt($varianceX * $varianceY);
        
        if ($denominator == 0) {
            return null;
        }
        
        return $covariance / $denominator;
    }
}

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

$data = [10, 12, 23, 23, 16, 23, 21, 16];

// 標準偏差
$stdDev = Statistics::standardDeviation($data);
echo "標準偏差: " . round($stdDev, 2) . "\n";

// 標本標準偏差
$sampleStdDev = Statistics::sampleStandardDeviation($data);
echo "標本標準偏差: " . round($sampleStdDev, 2) . "\n";

// RMS
$rms = Statistics::rms($data);
echo "二乗平均平方根: " . round($rms, 2) . "\n";

// 幾何平均
$values = [2, 8, 32];
$geoMean = Statistics::geometricMean($values);
echo "幾何平均[" . implode(', ', $values) . "]: " . round($geoMean, 2) . "\n";

// ユークリッドノルム
$vector = [3, 4];
$norm = Statistics::euclideanNorm($vector);
echo "ユークリッドノルム[" . implode(', ', $vector) . "]: {$norm}\n";

// 相関係数
$x = [1, 2, 3, 4, 5];
$y = [2, 4, 5, 4, 5];
$correlation = Statistics::correlation($x, $y);
echo "相関係数: " . round($correlation, 4) . "\n";

例3: 物理計算

class PhysicsCalculator {
    /**
     * 自由落下の時間から高さを計算
     */
    public static function fallHeight($time, $g = 9.8) {
        return 0.5 * $g * $time * $time;
    }
    
    /**
     * 高さから自由落下の時間を計算
     */
    public static function fallTime($height, $g = 9.8) {
        return sqrt(2 * $height / $g);
    }
    
    /**
     * 運動エネルギーから速度を計算
     */
    public static function velocityFromKE($kineticEnergy, $mass) {
        if ($mass <= 0) {
            return null;
        }
        
        return sqrt(2 * $kineticEnergy / $mass);
    }
    
    /**
     * 周期から振動数を計算
     */
    public static function frequency($period) {
        if ($period <= 0) {
            return null;
        }
        
        return 1 / $period;
    }
    
    /**
     * 単振り子の周期
     */
    public static function pendulumPeriod($length, $g = 9.8) {
        return 2 * M_PI * sqrt($length / $g);
    }
    
    /**
     * 脱出速度(第二宇宙速度)
     */
    public static function escapeVelocity($mass, $radius, $G = 6.674e-11) {
        return sqrt(2 * $G * $mass / $radius);
    }
    
    /**
     * 衝突時の速度(エネルギー保存)
     */
    public static function impactVelocity($height, $g = 9.8) {
        return sqrt(2 * $g * $height);
    }
    
    /**
     * 電磁波の周波数から波長
     */
    public static function wavelengthFromFrequency($frequency, $c = 299792458) {
        return $c / $frequency;
    }
    
    /**
     * 音速(温度による)
     */
    public static function soundSpeed($temperature) {
        // v = 331.5 + 0.6 * T (℃)
        return 331.5 + 0.6 * $temperature;
    }
}

// 使用例
echo "=== 物理計算 ===\n";

// 自由落下
$height = 20;
$fallTime = PhysicsCalculator::fallTime($height);
echo "{$height}mからの落下時間: " . round($fallTime, 2) . "秒\n";

$time = 2;
$fallHeight = PhysicsCalculator::fallHeight($time);
echo "{$time}秒間の落下距離: " . round($fallHeight, 2) . "m\n";

// 運動エネルギー
$ke = 100;  // J
$mass = 2;  // kg
$velocity = PhysicsCalculator::velocityFromKE($ke, $mass);
echo "運動エネルギー{$ke}J、質量{$mass}kgの速度: " . round($velocity, 2) . "m/s\n";

// 振り子の周期
$length = 1;  // m
$period = PhysicsCalculator::pendulumPeriod($length);
echo "長さ{$length}mの振り子の周期: " . round($period, 2) . "秒\n";

// 衝突速度
$impactVel = PhysicsCalculator::impactVelocity($height);
echo "{$height}mから落下時の衝突速度: " . round($impactVel, 2) . "m/s\n";

// 地球の脱出速度
$earthMass = 5.972e24;  // kg
$earthRadius = 6.371e6;  // m
$escapeVel = PhysicsCalculator::escapeVelocity($earthMass, $earthRadius);
echo "地球の脱出速度: " . round($escapeVel / 1000, 2) . "km/s\n";

例4: 金融計算

class FinancialCalculator {
    /**
     * 標準偏差(リスク)
     */
    public static function volatility($returns) {
        return Statistics::sampleStandardDeviation($returns);
    }
    
    /**
     * シャープレシオ
     */
    public static function sharpeRatio($returns, $riskFreeRate = 0) {
        $avgReturn = array_sum($returns) / count($returns);
        $stdDev = self::volatility($returns);
        
        if ($stdDev == 0) {
            return null;
        }
        
        return ($avgReturn - $riskFreeRate) / $stdDev;
    }
    
    /**
     * 年利から月利を計算
     */
    public static function annualToMonthlyRate($annualRate) {
        return pow(1 + $annualRate, 1/12) - 1;
    }
    
    /**
     * 複利の実効金利
     */
    public static function effectiveRate($nominalRate, $compounds) {
        return pow(1 + $nominalRate / $compounds, $compounds) - 1;
    }
    
    /**
     * ブラック・ショールズモデル(簡易版)
     */
    public static function blackScholesCallValue($S, $K, $T, $r, $sigma) {
        if ($T <= 0 || $sigma <= 0) {
            return null;
        }
        
        $d1 = (log($S / $K) + ($r + 0.5 * $sigma * $sigma) * $T) / 
              ($sigma * sqrt($T));
        $d2 = $d1 - $sigma * sqrt($T);
        
        // 正規分布の累積分布関数が必要だが簡略化
        return $S * self::normCdf($d1) - $K * exp(-$r * $T) * self::normCdf($d2);
    }
    
    /**
     * 正規分布の累積分布関数(近似)
     */
    private static function normCdf($x) {
        return 0.5 * (1 + erf($x / sqrt(2)));
    }
    
    /**
     * 幾何ブラウン運動のシミュレーション
     */
    public static function geometricBrownianMotion($S0, $mu, $sigma, $T, $steps) {
        $dt = $T / $steps;
        $prices = [$S0];
        $S = $S0;
        
        for ($i = 1; $i <= $steps; $i++) {
            // 正規分布に従う乱数(Box-Muller法)
            $u1 = mt_rand() / mt_getrandmax();
            $u2 = mt_rand() / mt_getrandmax();
            $z = sqrt(-2 * log($u1)) * cos(2 * M_PI * $u2);
            
            $S = $S * exp(($mu - 0.5 * $sigma * $sigma) * $dt + 
                          $sigma * sqrt($dt) * $z);
            $prices[] = $S;
        }
        
        return $prices;
    }
}

// 使用例
echo "=== 金融計算 ===\n";

// リターンデータ
$returns = [0.05, -0.02, 0.03, 0.01, -0.01, 0.04, 0.02];

// ボラティリティ
$vol = FinancialCalculator::volatility($returns);
echo "ボラティリティ(リスク): " . round($vol * 100, 2) . "%\n";

// シャープレシオ
$sharpe = FinancialCalculator::sharpeRatio($returns, 0.02);
echo "シャープレシオ: " . round($sharpe, 4) . "\n";

// 年利から月利
$annualRate = 0.12;
$monthlyRate = FinancialCalculator::annualToMonthlyRate($annualRate);
echo "年利{$annualRate}の月利: " . round($monthlyRate * 100, 4) . "%\n";

// 実効金利
$nominalRate = 0.10;
$compounds = 12;
$effectiveRate = FinancialCalculator::effectiveRate($nominalRate, $compounds);
echo "名目年利{$nominalRate}(月次複利)の実効年利: " . round($effectiveRate * 100, 2) . "%\n";

// 幾何ブラウン運動
echo "\n=== 株価シミュレーション ===\n";
$S0 = 100;  // 初期価格
$mu = 0.10;  // ドリフト
$sigma = 0.20;  // ボラティリティ
$T = 1;  // 1年
$steps = 5;

$simulation = FinancialCalculator::geometricBrownianMotion($S0, $mu, $sigma, $T, $steps);
foreach ($simulation as $i => $price) {
    $month = $i * ($T / $steps) * 12;
    echo sprintf("%.1fヶ月: %.2f円\n", $month, $price);
}

例5: 画像処理

class ImageProcessor {
    /**
     * ピクセル間の色差(ユークリッド距離)
     */
    public static function colorDistance($rgb1, $rgb2) {
        $dr = $rgb1['r'] - $rgb2['r'];
        $dg = $rgb1['g'] - $rgb2['g'];
        $db = $rgb1['b'] - $rgb2['b'];
        
        return sqrt($dr * $dr + $dg * $dg + $db * $db);
    }
    
    /**
     * グレースケールへの変換
     */
    public static function toGrayscale($rgb) {
        // 明度の計算
        return sqrt(
            0.299 * $rgb['r'] * $rgb['r'] +
            0.587 * $rgb['g'] * $rgb['g'] +
            0.114 * $rgb['b'] * $rgb['b']
        );
    }
    
    /**
     * 画像のブラー(ガウシアンフィルタの標準偏差)
     */
    public static function gaussianKernel($sigma, $size = null) {
        if ($size === null) {
            $size = ceil($sigma * 3) * 2 + 1;
        }
        
        $kernel = [];
        $sum = 0;
        $center = floor($size / 2);
        
        for ($y = 0; $y < $size; $y++) {
            for ($x = 0; $x < $size; $x++) {
                $dx = $x - $center;
                $dy = $y - $center;
                $distance = sqrt($dx * $dx + $dy * $dy);
                
                $value = exp(-($distance * $distance) / (2 * $sigma * $sigma));
                $kernel[$y][$x] = $value;
                $sum += $value;
            }
        }
        
        // 正規化
        for ($y = 0; $y < $size; $y++) {
            for ($x = 0; $x < $size; $x++) {
                $kernel[$y][$x] /= $sum;
            }
        }
        
        return $kernel;
    }
    
    /**
     * 2つの画像の類似度(平均二乗誤差のルート、RMSE)
     */
    public static function imageSimilarity($pixels1, $pixels2) {
        if (count($pixels1) !== count($pixels2)) {
            return null;
        }
        
        $sumSquaredDiff = 0;
        $count = count($pixels1);
        
        for ($i = 0; $i < $count; $i++) {
            $diff = $pixels1[$i] - $pixels2[$i];
            $sumSquaredDiff += $diff * $diff;
        }
        
        return sqrt($sumSquaredDiff / $count);
    }
}

// 使用例
echo "=== 画像処理 ===\n";

// 色差の計算
$color1 = ['r' => 255, 'g' => 0, 'b' => 0];     // 赤
$color2 = ['r' => 0, 'g' => 255, 'b' => 0];     // 緑
$distance = ImageProcessor::colorDistance($color1, $color2);
echo "色差(赤と緑): " . round($distance, 2) . "\n";

// グレースケール変換
$color = ['r' => 128, 'g' => 192, 'b' => 64];
$gray = ImageProcessor::toGrayscale($color);
echo "グレースケール値: " . round($gray) . "\n";

// ガウシアンカーネル
echo "\n=== ガウシアンカーネル(3×3、σ=1.0) ===\n";
$kernel = ImageProcessor::gaussianKernel(1.0, 3);
foreach ($kernel as $row) {
    foreach ($row as $value) {
        echo sprintf("%.4f ", $value);
    }
    echo "\n";
}

// 画像の類似度
$pixels1 = [100, 150, 200, 120, 180];
$pixels2 = [102, 148, 205, 118, 182];
$rmse = ImageProcessor::imageSimilarity($pixels1, $pixels2);
echo "\n画像の類似度(RMSE): " . round($rmse, 2) . "\n";

例6: ゲーム開発

class GameMath {
    /**
     * 速度ベクトルの大きさ(速さ)
     */
    public static function speed($vx, $vy) {
        return sqrt($vx * $vx + $vy * $vy);
    }
    
    /**
     * 加速度から速度を計算
     */
    public static function velocityFromAcceleration($acceleration, $time) {
        return sqrt(2 * $acceleration * $time);
    }
    
    /**
     * 衝突検出(円と円)
     */
    public static function circleCollision($x1, $y1, $r1, $x2, $y2, $r2) {
        $dx = $x2 - $x1;
        $dy = $y2 - $y1;
        $distance = sqrt($dx * $dx + $dy * $dy);
        
        return $distance < ($r1 + $r2);
    }
    
    /**
     * カメラからの距離(3D)
     */
    public static function cameraDistance($objectX, $objectY, $objectZ, 
                                          $cameraX, $cameraY, $cameraZ) {
        $dx = $objectX - $cameraX;
        $dy = $objectY - $cameraY;
        $dz = $objectZ - $cameraZ;
        
        return sqrt($dx * $dx + $dy * $dy + $dz * $dz);
    }
    
    /**
     * ベクトルの正規化
     */
    public static function normalize($x, $y) {
        $length = sqrt($x * $x + $y * $y);
        
        if ($length == 0) {
            return ['x' => 0, 'y' => 0];
        }
        
        return [
            'x' => $x / $length,
            'y' => $y / $length
        ];
    }
    
    /**
     * パーリンノイズの補間関数
     */
    public static function smoothstep($t) {
        return $t * $t * (3 - 2 * $t);
    }
}

// 使用例
echo "=== ゲーム開発の計算 ===\n";

// 速度の計算
$vx = 3;
$vy = 4;
$speed = GameMath::speed($vx, $vy);
echo "速度ベクトル({$vx}, {$vy})の速さ: {$speed}\n";

// 衝突検出
$circle1 = ['x' => 0, 'y' => 0, 'r' => 5];
$circle2 = ['x' => 8, 'y' => 0, 'r' => 5];
$collision = GameMath::circleCollision(
    $circle1['x'], $circle1['y'], $circle1['r'],
    $circle2['x'], $circle2['y'], $circle2['r']
);
echo "衝突判定: " . ($collision ? '衝突' : '非衝突') . "\n";

// カメラ距離
$camera = ['x' => 0, 'y' => 0, 'z' => 0];
$object = ['x' => 3, 'y' => 4, 'z' => 12];
$distance = GameMath::cameraDistance(
    $object['x'], $object['y'], $object['z'],
    $camera['x'], $camera['y'], $camera['z']
);
echo "カメラからの距離: {$distance}\n";

// ベクトルの正規化
$vector = ['x' => 6, 'y' => 8];
$normalized = GameMath::normalize($vector['x'], $vector['y']);
echo "正規化ベクトル: (" . round($normalized['x'], 2) . ", " . 
     round($normalized['y'], 2) . ")\n";

pow()関数との関係

// sqrt(x)はpow(x, 0.5)と同じ
$num = 16;

echo sqrt($num);        // 4
echo pow($num, 0.5);    // 4
echo pow($num, 1/2);    // 4

// パフォーマンス比較(sqrtの方が高速)
$iterations = 1000000;

$start = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
    sqrt(123456789);
}
$time_sqrt = microtime(true) - $start;

$start = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
    pow(123456789, 0.5);
}
$time_pow = microtime(true) - $start;

echo "sqrt(): {$time_sqrt}秒\n";
echo "pow(): {$time_pow}秒\n";
// sqrt()の方が通常高速

まとめ

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

できること:

  • 平方根(√)の計算
  • 距離の計算
  • 標準偏差の計算
  • ベクトルの大きさ

引数と戻り値:

  • 引数: 0以上の数値
  • 戻り値: 平方根の値
  • 負の数: NANを返す

推奨される使用場面:

  • 幾何学計算
  • 統計処理
  • 物理シミュレーション
  • 金融計算
  • ゲーム開発
  • 画像処理

重要な公式:

// 三平方の定理
$c = sqrt($a * $a + $b * $b);

// 2点間の距離
$d = sqrt(pow($x2 - $x1, 2) + pow($y2 - $y1, 2));

// 標準偏差
$σ = sqrt($variance);

関連関数:

  • pow(): べき乗計算
  • hypot(): 直角三角形の斜辺
  • log(): 対数
  • exp(): 指数関数

よく使うパターン:

// 距離計算
$distance = sqrt($dx * $dx + $dy * $dy);

// ベクトルの正規化
$length = sqrt($x * $x + $y * $y);
$normalized_x = $x / $length;

// 標準偏差
$stdDev = sqrt($variance);

// 安全な計算
$result = $num >= 0 ? sqrt($num) : null;

sqrt()は、数学、科学、工学、プログラミングのあらゆる分野で使われる最も基本的で重要な関数の一つです。距離計算や統計処理など、様々な場面で活躍します!

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