[PHP]log10関数完全解説 – 常用対数の計算と実用的な活用法を詳しく解説

PHP

PHPで数学計算や科学計算を行う際、10を底とする対数(常用対数)が必要な場面があります。そんなときに便利なのがlog10関数です。この記事では、log10関数の基本的な使い方から実際のプログラムでの活用方法まで、サンプルコードを交えながら詳しく解説していきます。

log10関数とは?

log10関数は、10を底とする対数(常用対数)を計算するPHPの数学関数です。常用対数は科学技術分野で広く使用されており、pH値、デシベル、地震の規模(リヒタースケール)、星の明るさなど、身の回りの現象を表現する際によく使われます。

基本的な構文

float log10(float $arg)

パラメータ

  • $arg: 常用対数を求める正の数値

返り値

  • 10を底とする対数値(float型)
  • 引数が0以下の場合は-INFまたはNANを返す

基本的な使用例

基本的な常用対数の計算

<?php
// 基本的な常用対数の計算
echo "log10(1) = " . log10(1) . "\n";        // 0 (10^0 = 1)
echo "log10(10) = " . log10(10) . "\n";      // 1 (10^1 = 10)
echo "log10(100) = " . log10(100) . "\n";    // 2 (10^2 = 100)
echo "log10(1000) = " . log10(1000) . "\n";  // 3 (10^3 = 1000)
echo "log10(0.1) = " . log10(0.1) . "\n";    // -1 (10^-1 = 0.1)
echo "log10(0.01) = " . log10(0.01) . "\n";  // -2 (10^-2 = 0.01)

// 任意の値
echo "log10(50) = " . log10(50) . "\n";      // 1.698970...
echo "log10(3.14) = " . log10(3.14) . "\n";  // 0.496929...
?>

log関数との比較

<?php
$test_values = [1, 10, 100, 1000, 0.1];

echo "log10関数とlog関数の比較:\n";
foreach ($test_values as $value) {
    $log10_result = log10($value);
    $log_result = log($value, 10); // log関数で底10を指定
    
    echo "値: {$value}\n";
    echo "  log10({$value}) = {$log10_result}\n";
    echo "  log({$value}, 10) = {$log_result}\n";
    echo "  差: " . abs($log10_result - $log_result) . "\n\n";
}
?>

実践的な活用例

科学計算・物理現象の表現

<?php
class ScienceCalculator {
    /**
     * pH値の計算
     * pH = -log10([H+])
     */
    public static function calculatePH($hydrogen_concentration) {
        if ($hydrogen_concentration <= 0) {
            throw new InvalidArgumentException("水素イオン濃度は正の値である必要があります");
        }
        
        return -log10($hydrogen_concentration);
    }
    
    /**
     * デシベル(dB)の計算
     * dB = 10 * log10(P/P0)
     */
    public static function calculateDecibel($power, $reference_power = 1) {
        if ($power <= 0 || $reference_power <= 0) {
            throw new InvalidArgumentException("電力値は正の値である必要があります");
        }
        
        return 10 * log10($power / $reference_power);
    }
    
    /**
     * 地震のマグニチュード計算(リヒタースケール)
     * M = log10(A/A0)
     */
    public static function calculateMagnitude($amplitude, $reference_amplitude = 1) {
        if ($amplitude <= 0 || $reference_amplitude <= 0) {
            throw new InvalidArgumentException("振幅は正の値である必要があります");
        }
        
        return log10($amplitude / $reference_amplitude);
    }
    
    /**
     * 星の等級差の計算
     * 等級差 = -2.5 * log10(明るさの比)
     */
    public static function calculateMagnitudeDifference($brightness1, $brightness2) {
        if ($brightness1 <= 0 || $brightness2 <= 0) {
            throw new InvalidArgumentException("明るさは正の値である必要があります");
        }
        
        return -2.5 * log10($brightness1 / $brightness2);
    }
}

// 使用例
try {
    // pH値の計算
    $ph_neutral = ScienceCalculator::calculatePH(1e-7); // 中性
    $ph_acidic = ScienceCalculator::calculatePH(1e-3);  // 酸性
    $ph_basic = ScienceCalculator::calculatePH(1e-9);   // 塩基性
    
    echo "pH値の計算:\n";
    echo "中性(H+ = 1e-7): pH = " . round($ph_neutral, 1) . "\n";
    echo "酸性(H+ = 1e-3): pH = " . round($ph_acidic, 1) . "\n";
    echo "塩基性(H+ = 1e-9): pH = " . round($ph_basic, 1) . "\n\n";
    
    // デシベル計算
    $sound_levels = [
        '図書館' => 0.000001,
        '普通の会話' => 0.001,
        '交通騒音' => 0.1,
        '飛行機' => 10
    ];
    
    echo "音のレベル(デシベル):\n";
    foreach ($sound_levels as $source => $power) {
        $db = ScienceCalculator::calculateDecibel($power);
        echo "{$source}: " . round($db, 1) . " dB\n";
    }
    
} catch (Exception $e) {
    echo "エラー: " . $e->getMessage() . "\n";
}
?>

データ分析・統計処理

<?php
class DataAnalyzer {
    /**
     * 桁数の計算
     */
    public static function getDigitCount($number) {
        if ($number <= 0) {
            return 1;
        }
        return floor(log10($number)) + 1;
    }
    
    /**
     * オーダー(桁)による分類
     */
    public static function classifyByOrder($numbers) {
        $classification = [];
        
        foreach ($numbers as $number) {
            if ($number <= 0) {
                $classification['invalid'][] = $number;
                continue;
            }
            
            $order = floor(log10($number));
            $range_key = "10^{$order} - 10^" . ($order + 1);
            
            if (!isset($classification[$range_key])) {
                $classification[$range_key] = [];
            }
            $classification[$range_key][] = $number;
        }
        
        return $classification;
    }
    
    /**
     * 対数スケールでのヒストグラム作成
     */
    public static function createLogHistogram($data, $bins = 10) {
        $valid_data = array_filter($data, function($x) { return $x > 0; });
        
        if (empty($valid_data)) {
            return [];
        }
        
        $min_log = log10(min($valid_data));
        $max_log = log10(max($valid_data));
        $bin_width = ($max_log - $min_log) / $bins;
        
        $histogram = [];
        
        for ($i = 0; $i < $bins; $i++) {
            $lower_bound = $min_log + $i * $bin_width;
            $upper_bound = $min_log + ($i + 1) * $bin_width;
            
            $lower_value = pow(10, $lower_bound);
            $upper_value = pow(10, $upper_bound);
            
            $count = 0;
            foreach ($valid_data as $value) {
                $log_value = log10($value);
                if ($log_value >= $lower_bound && $log_value < $upper_bound) {
                    $count++;
                }
            }
            
            $histogram[] = [
                'range' => sprintf("%.2f - %.2f", $lower_value, $upper_value),
                'count' => $count,
                'log_range' => sprintf("10^%.1f - 10^%.1f", $lower_bound, $upper_bound)
            ];
        }
        
        return $histogram;
    }
}

// 使用例
$sample_data = [5, 23, 156, 1247, 8934, 45623, 234567, 1234567, 9876543];

echo "データの桁数分析:\n";
foreach ($sample_data as $number) {
    $digits = DataAnalyzer::getDigitCount($number);
    echo "{$number}: {$digits}桁\n";
}

echo "\nオーダー別分類:\n";
$classification = DataAnalyzer::classifyByOrder($sample_data);
foreach ($classification as $range => $numbers) {
    echo "{$range}: " . count($numbers) . "個 (" . implode(', ', $numbers) . ")\n";
}

echo "\n対数ヒストグラム:\n";
$histogram = DataAnalyzer::createLogHistogram($sample_data, 5);
foreach ($histogram as $bin) {
    echo "{$bin['range']}: {$bin['count']}個\n";
}
?>

ファイルサイズ・メモリ使用量の分析

<?php
class SystemAnalyzer {
    /**
     * ファイルサイズの単位変換
     */
    public static function formatFileSize($bytes) {
        if ($bytes <= 0) {
            return '0 B';
        }
        
        $units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
        $power = floor(log10($bytes) / 3); // 1000進で計算
        $power = min($power, count($units) - 1);
        
        $size = $bytes / pow(1000, $power);
        
        return round($size, 2) . ' ' . $units[$power];
    }
    
    /**
     * ファイルサイズの分布分析
     */
    public static function analyzeFileSizes($file_sizes) {
        $analysis = [
            'tiny' => 0,      // < 1KB
            'small' => 0,     // 1KB - 100KB
            'medium' => 0,    // 100KB - 10MB
            'large' => 0,     // 10MB - 1GB
            'huge' => 0       // > 1GB
        ];
        
        foreach ($file_sizes as $size) {
            if ($size <= 0) continue;
            
            $log_size = log10($size);
            
            if ($log_size < 3) {           // < 10^3 = 1000 bytes
                $analysis['tiny']++;
            } elseif ($log_size < 5) {     // < 10^5 = 100KB
                $analysis['small']++;
            } elseif ($log_size < 7) {     // < 10^7 = 10MB
                $analysis['medium']++;
            } elseif ($log_size < 9) {     // < 10^9 = 1GB
                $analysis['large']++;
            } else {
                $analysis['huge']++;
            }
        }
        
        return $analysis;
    }
    
    /**
     * メモリ使用量の推移分析
     */
    public static function analyzeMemoryUsage($memory_snapshots) {
        $growth_rates = [];
        
        for ($i = 1; $i < count($memory_snapshots); $i++) {
            $current = $memory_snapshots[$i];
            $previous = $memory_snapshots[$i - 1];
            
            if ($previous > 0 && $current > 0) {
                // 成長率 = log10(現在/前回)
                $growth_rate = log10($current / $previous);
                $growth_rates[] = $growth_rate;
            }
        }
        
        if (empty($growth_rates)) {
            return null;
        }
        
        $avg_growth = array_sum($growth_rates) / count($growth_rates);
        
        return [
            'average_growth_rate' => $avg_growth,
            'growth_factor' => pow(10, $avg_growth),
            'trend' => $avg_growth > 0.01 ? 'increasing' : 
                      ($avg_growth < -0.01 ? 'decreasing' : 'stable')
        ];
    }
}

// 使用例
$file_sizes = [
    512,        // 512 bytes
    2048,       // 2KB
    51200,      // 50KB
    1048576,    // 1MB
    10485760,   // 10MB
    1073741824, // 1GB
    5368709120  // 5GB
];

echo "ファイルサイズの表示:\n";
foreach ($file_sizes as $size) {
    echo SystemAnalyzer::formatFileSize($size) . " ({$size} bytes)\n";
}

echo "\nファイルサイズ分布:\n";
$size_distribution = SystemAnalyzer::analyzeFileSizes($file_sizes);
foreach ($size_distribution as $category => $count) {
    echo "{$category}: {$count}ファイル\n";
}

// メモリ使用量の分析例
$memory_usage = [1000000, 1200000, 1500000, 2000000, 1800000, 2200000];
echo "\nメモリ使用量分析:\n";
$memory_analysis = SystemAnalyzer::analyzeMemoryUsage($memory_usage);
if ($memory_analysis) {
    echo "平均成長率: " . round($memory_analysis['average_growth_rate'], 4) . "\n";
    echo "成長倍率: " . round($memory_analysis['growth_factor'], 3) . "\n";
    echo "トレンド: " . $memory_analysis['trend'] . "\n";
}
?>

Web解析・パフォーマンス測定

<?php
class WebAnalyzer {
    /**
     * ページビューの規模分類
     */
    public static function classifyPageViews($page_views) {
        if ($page_views <= 0) {
            return 'none';
        }
        
        $log_views = log10($page_views);
        
        if ($log_views < 2) {          // < 100
            return 'small';
        } elseif ($log_views < 3) {    // < 1,000
            return 'medium';
        } elseif ($log_views < 4) {    // < 10,000
            return 'popular';
        } elseif ($log_views < 5) {    // < 100,000
            return 'viral';
        } else {                       // >= 100,000
            return 'massive';
        }
    }
    
    /**
     * レスポンスタイムの分析
     */
    public static function analyzeResponseTimes($response_times) {
        $buckets = [
            'excellent' => 0,    // < 100ms
            'good' => 0,         // 100ms - 1s
            'acceptable' => 0,   // 1s - 3s
            'slow' => 0,         // 3s - 10s
            'critical' => 0      // > 10s
        ];
        
        foreach ($response_times as $time) {
            if ($time <= 0) continue;
            
            $log_time = log10($time);
            
            if ($log_time < -1) {        // < 0.1s = 100ms
                $buckets['excellent']++;
            } elseif ($log_time < 0) {   // < 1s
                $buckets['good']++;
            } elseif ($log_time < 0.477) { // < 3s (log10(3) ≈ 0.477)
                $buckets['acceptable']++;
            } elseif ($log_time < 1) {   // < 10s
                $buckets['slow']++;
            } else {
                $buckets['critical']++;
            }
        }
        
        return $buckets;
    }
    
    /**
     * トラフィックの成長分析
     */
    public static function analyzeTrafficGrowth($daily_visitors) {
        if (count($daily_visitors) < 2) {
            return null;
        }
        
        $growth_rates = [];
        
        for ($i = 1; $i < count($daily_visitors); $i++) {
            $today = $daily_visitors[$i];
            $yesterday = $daily_visitors[$i - 1];
            
            if ($yesterday > 0 && $today > 0) {
                $growth_rate = log10($today / $yesterday);
                $growth_rates[] = $growth_rate;
            }
        }
        
        if (empty($growth_rates)) {
            return null;
        }
        
        $avg_daily_growth = array_sum($growth_rates) / count($growth_rates);
        $monthly_growth = 30 * $avg_daily_growth; // 30日間の成長
        
        return [
            'daily_growth_rate' => $avg_daily_growth,
            'daily_growth_factor' => pow(10, $avg_daily_growth),
            'projected_monthly_factor' => pow(10, $monthly_growth),
            'growth_classification' => self::classifyGrowth($avg_daily_growth)
        ];
    }
    
    private static function classifyGrowth($growth_rate) {
        if ($growth_rate > 0.1) {
            return 'explosive';
        } elseif ($growth_rate > 0.01) {
            return 'rapid';
        } elseif ($growth_rate > 0.001) {
            return 'moderate';
        } elseif ($growth_rate > -0.001) {
            return 'stable';
        } else {
            return 'declining';
        }
    }
}

// 使用例
$page_views_data = [45, 234, 1567, 8934, 45623, 234567];

echo "ページビュー分類:\n";
foreach ($page_views_data as $views) {
    $classification = WebAnalyzer::classifyPageViews($views);
    echo "{$views} PV: {$classification}\n";
}

$response_times = [0.05, 0.12, 0.8, 1.5, 2.8, 5.2, 12.3];
echo "\nレスポンスタイム分析:\n";
$response_analysis = WebAnalyzer::analyzeResponseTimes($response_times);
foreach ($response_analysis as $category => $count) {
    echo "{$category}: {$count}件\n";
}

// トラフィック成長分析
$daily_visitors = [1000, 1050, 1100, 1200, 1150, 1300, 1400, 1500];
echo "\nトラフィック成長分析:\n";
$growth_analysis = WebAnalyzer::analyzeTrafficGrowth($daily_visitors);
if ($growth_analysis) {
    echo "日次成長率: " . round($growth_analysis['daily_growth_rate'], 4) . "\n";
    echo "日次成長倍率: " . round($growth_analysis['daily_growth_factor'], 3) . "倍\n";
    echo "月間予測倍率: " . round($growth_analysis['projected_monthly_factor'], 2) . "倍\n";
    echo "成長分類: " . $growth_analysis['growth_classification'] . "\n";
}
?>

エラーハンドリングと特殊ケース

入力値の検証

<?php
function safeLog10($value) {
    // 数値チェック
    if (!is_numeric($value)) {
        throw new InvalidArgumentException("数値が必要です: " . var_export($value, true));
    }
    
    $value = (float)$value;
    
    // 範囲チェック
    if ($value <= 0) {
        throw new InvalidArgumentException("正の値が必要です: {$value}");
    }
    
    // 結果の検証
    $result = log10($value);
    
    if (!is_finite($result)) {
        throw new RuntimeException("計算結果が無限大またはNaNです");
    }
    
    return $result;
}

// テストケース
$test_cases = [10, 0, -5, "abc", 1e-100, 1e100, INF, NAN];

foreach ($test_cases as $test) {
    try {
        $result = safeLog10($test);
        echo "log10(" . var_export($test, true) . ") = {$result}\n";
    } catch (Exception $e) {
        echo "エラー(" . var_export($test, true) . "): " . $e->getMessage() . "\n";
    }
}
?>

特殊値での動作

<?php
echo "特殊値でのlog10関数の動作:\n\n";

// 正常値
echo "正常値:\n";
echo "log10(1) = " . log10(1) . "\n";
echo "log10(10) = " . log10(10) . "\n";
echo "log10(100) = " . log10(100) . "\n";

// 小数値
echo "\n小数値:\n";
echo "log10(0.1) = " . log10(0.1) . "\n";
echo "log10(0.01) = " . log10(0.01) . "\n";

// 極値
echo "\n極値:\n";
echo "log10(1e-10) = " . log10(1e-10) . "\n";
echo "log10(1e10) = " . log10(1e10) . "\n";

// 特殊値(警告が発生する可能性)
echo "\n特殊値:\n";
error_reporting(E_ALL);

echo "log10(0) = " . log10(0) . "\n";        // -INF
echo "log10(-1) = " . log10(-1) . "\n";      // NAN
echo "log10(INF) = " . log10(INF) . "\n";    // INF
echo "log10(NAN) = " . log10(NAN) . "\n";    // NAN
?>

パフォーマンス最適化

大量データの効率的処理

<?php
class OptimizedLog10Calculator {
    private static $cache = [];
    private static $cache_hits = 0;
    private static $cache_misses = 0;
    
    /**
     * キャッシュ機能付きlog10計算
     */
    public static function cachedLog10($value, $precision = 6) {
        $rounded_value = round($value, $precision);
        
        if (isset(self::$cache[$rounded_value])) {
            self::$cache_hits++;
            return self::$cache[$rounded_value];
        }
        
        self::$cache_misses++;
        $result = log10($value);
        self::$cache[$rounded_value] = $result;
        
        return $result;
    }
    
    /**
     * バッチ処理
     */
    public static function batchLog10($data) {
        $start_time = microtime(true);
        $results = [];
        $valid_count = 0;
        
        foreach ($data as $value) {
            if (is_numeric($value) && $value > 0) {
                $results[] = log10($value);
                $valid_count++;
            } else {
                $results[] = null;
            }
        }
        
        $end_time = microtime(true);
        
        return [
            'results' => $results,
            'processing_time' => $end_time - $start_time,
            'valid_count' => $valid_count,
            'invalid_count' => count($data) - $valid_count,
            'throughput' => $valid_count / ($end_time - $start_time)
        ];
    }
    
    /**
     * キャッシュ統計
     */
    public static function getCacheStats() {
        $total_requests = self::$cache_hits + self::$cache_misses;
        
        return [
            'cache_size' => count(self::$cache),
            'cache_hits' => self::$cache_hits,
            'cache_misses' => self::$cache_misses,
            'hit_rate' => $total_requests > 0 ? self::$cache_hits / $total_requests : 0
        ];
    }
    
    /**
     * キャッシュクリア
     */
    public static function clearCache() {
        self::$cache = [];
        self::$cache_hits = 0;
        self::$cache_misses = 0;
    }
}

// パフォーマンステスト
$large_dataset = array_map(function($x) { return $x * 1.1; }, range(1, 50000));

echo "バッチ処理テスト:\n";
$batch_result = OptimizedLog10Calculator::batchLog10($large_dataset);

echo "処理件数: " . $batch_result['valid_count'] . "/" . count($large_dataset) . "\n";
echo "処理時間: " . round($batch_result['processing_time'] * 1000, 2) . " ms\n";
echo "スループット: " . round($batch_result['throughput']) . " items/sec\n";

// キャッシュテスト
echo "\nキャッシュテスト:\n";
OptimizedLog10Calculator::clearCache();

// 同じ値を複数回計算
$repeated_values = array_fill(0, 1000, 123.456);
foreach ($repeated_values as $value) {
    OptimizedLog10Calculator::cachedLog10($value);
}

$cache_stats = OptimizedLog10Calculator::getCacheStats();
echo "キャッシュサイズ: " . $cache_stats['cache_size'] . "\n";
echo "ヒット率: " . round($cache_stats['hit_rate'] * 100, 2) . "%\n";
?>

実用的なユーティリティ関数

汎用ヘルパークラス

<?php
class Log10Utils {
    /**
     * 数値を対数スケールで正規化
     */
    public static function normalizeLogScale($values, $min_output = 0, $max_output = 1) {
        $valid_values = array_filter($values, function($x) { return is_numeric($x) && $x > 0; });
        
        if (empty($valid_values)) {
            return array_fill(0, count($values), null);
        }
        
        $log_values = array_map('log10', $valid_values);
        $min_log = min($log_values);
        $max_log = max($log_values);
        
        $range = $max_log - $min_log;
        if ($range == 0) {
            return array_fill(0, count($values), $min_output);
        }
        
        $result = [];
        foreach ($values as $value) {
            if (is_numeric($value) && $value > 0) {
                $log_value = log10($value);
                $normalized = ($log_value - $min_log) / $range;
                $result[] = $min_output + $normalized * ($max_output - $min_output);
            } else {
                $result[] = null;
            }
        }
        
        return $result;
    }
    
    /**
     * 対数スケールでの補間
     */
    public static function logInterpolate($x1, $y1, $x2, $y2, $x) {
        if ($x1 <= 0 || $x2 <= 0 || $y1 <= 0 || $y2 <= 0 || $x <= 0) {
            throw new InvalidArgumentException("すべての値は正の数である必要があります");
        }
        
        $log_x1 = log10($x1);
        $log_x2 = log10($x2);
        $log_y1 = log10($y1);
        $log_y2 = log10($y2);
        $log_x = log10($x);
        
        $log_y = $log_y1 + ($log_y2 - $log_y1) * ($log_x - $log_x1) / ($log_x2 - $log_x1);
        
        return pow(10, $log_y);
    }
    
    /**
     * 対数スケールでの配列生成
     */
    public static function logSpace($start, $end, $num = 50) {
        if ($start <= 0 || $end <= 0) {
            throw new InvalidArgumentException("開始値と終了値は正の数である必要があります");
        }
        
        $log_start = log10($start);
        $log_end = log10($end);
        $log_step = ($log_end - $log_start) / ($num - 1);
        
        $result = [];
        for ($i = 0; $i < $num; $i++) {
            $log_value = $log_start + $i * $log_step;
            $result[] = pow(10, $log_value);
        }
        
        return $result;
    }
}

// 使用例
$test_data = [1, 10, 100, 1000, 10000];

echo "対数スケール正規化:\n";
$normalized = Log10Utils::normalizeLogScale($test_data, 0, 100);
foreach ($test_data as $i => $value) {
    echo "{$value} -> " . round($normalized[$i], 2) . "\n";
}

echo "\n対数補間の例:\n";
try {
    $interpolated = Log10Utils::logInterpolate(10, 100, 100, 1000, 50);
    echo "x=50での補間値: " . round($interpolated, 2) . "\n";
} catch (Exception $e) {
    echo "エラー: " . $e->getMessage() . "\n";
}

echo "\n対数スケール配列生成:\n";
$log_array = Log10Utils::logSpace(1, 1000, 6);
foreach ($log_array as $value) {
    echo round($value, 2) . " ";
}
echo "\n";
?>

より高度な応用例

機械学習・データサイエンス

<?php
class MLDataProcessor {
    /**
     * 特徴量の対数変換
     * 右に歪んだ分布を正規分布に近づける
     */
    public static function logTransformFeatures($features, $offset = 1) {
        $transformed = [];
        
        foreach ($features as $feature_set) {
            $transformed_set = [];
            foreach ($feature_set as $value) {
                if (is_numeric($value)) {
                    // 0や負の値を避けるためのオフセット
                    $adjusted_value = $value + $offset;
                    $transformed_set[] = log10($adjusted_value);
                } else {
                    $transformed_set[] = null;
                }
            }
            $transformed[] = $transformed_set;
        }
        
        return $transformed;
    }
    
    /**
     * 情報ゲインの計算(決定木で使用)
     */
    public static function calculateInformationGain($parent_counts, $child_splits) {
        $total_samples = array_sum($parent_counts);
        if ($total_samples == 0) return 0;
        
        // 親ノードのエントロピー
        $parent_entropy = 0;
        foreach ($parent_counts as $count) {
            if ($count > 0) {
                $probability = $count / $total_samples;
                $parent_entropy -= $probability * log10($probability) / log10(2); // log2に変換
            }
        }
        
        // 子ノードの重み付きエントロピー
        $weighted_entropy = 0;
        foreach ($child_splits as $child) {
            $child_total = array_sum($child);
            if ($child_total > 0) {
                $child_entropy = 0;
                foreach ($child as $count) {
                    if ($count > 0) {
                        $probability = $count / $child_total;
                        $child_entropy -= $probability * log10($probability) / log10(2);
                    }
                }
                $weighted_entropy += ($child_total / $total_samples) * $child_entropy;
            }
        }
        
        return $parent_entropy - $weighted_entropy;
    }
}

// 使用例
$sample_features = [
    [1, 10, 100],
    [2, 20, 200],
    [5, 50, 500],
    [10, 100, 1000]
];

echo "特徴量の対数変換:\n";
echo "元データ:\n";
foreach ($sample_features as $i => $features) {
    echo "サンプル" . ($i + 1) . ": [" . implode(', ', $features) . "]\n";
}

$log_features = MLDataProcessor::logTransformFeatures($sample_features);
echo "\n対数変換後:\n";
foreach ($log_features as $i => $features) {
    $formatted = array_map(function($x) { return round($x, 3); }, $features);
    echo "サンプル" . ($i + 1) . ": [" . implode(', ', $formatted) . "]\n";
}

// 情報ゲインの計算例
$parent_counts = [30, 20]; // クラス1: 30個, クラス2: 20個
$child_splits = [
    [20, 5],  // 左の子ノード: クラス1: 20個, クラス2: 5個
    [10, 15]  // 右の子ノード: クラス1: 10個, クラス2: 15個
];

$info_gain = MLDataProcessor::calculateInformationGain($parent_counts, $child_splits);
echo "\n情報ゲイン: " . round($info_gain, 4) . "\n";
?>

金融・リスク分析

<?php
class FinancialRiskAnalyzer {
    /**
     * VaR(Value at Risk)の計算
     * 対数正規分布を仮定
     */
    public static function calculateVaR($returns, $confidence_level = 0.05, $initial_value = 1000000) {
        $valid_returns = array_filter($returns, 'is_numeric');
        
        if (count($valid_returns) < 2) {
            throw new InvalidArgumentException("十分なデータがありません");
        }
        
        // 対数リターンに変換
        $log_returns = [];
        foreach ($valid_returns as $return) {
            if ($return > 0) {
                $log_returns[] = log10(1 + $return);
            }
        }
        
        if (empty($log_returns)) {
            throw new InvalidArgumentException("正のリターンが必要です");
        }
        
        // 平均と標準偏差を計算
        $mean = array_sum($log_returns) / count($log_returns);
        $variance = 0;
        
        foreach ($log_returns as $log_return) {
            $variance += pow($log_return - $mean, 2);
        }
        $variance /= count($log_returns) - 1;
        $std_dev = sqrt($variance);
        
        // Z値(標準正規分布の分位点)を近似
        $z_score = self::getZScore($confidence_level);
        
        // VaRを計算
        $var_log = $mean - $z_score * $std_dev;
        $var_factor = pow(10, $var_log);
        
        $var_amount = $initial_value * (1 - $var_factor);
        
        return [
            'var_amount' => $var_amount,
            'var_percentage' => (1 - $var_factor) * 100,
            'confidence_level' => (1 - $confidence_level) * 100
        ];
    }
    
    private static function getZScore($alpha) {
        // 簡略化した標準正規分布の分位点近似
        if ($alpha <= 0.01) return 2.33;
        if ($alpha <= 0.05) return 1.645;
        if ($alpha <= 0.10) return 1.28;
        return 1.0;
    }
    
    /**
     * ポートフォリオのリスク分散効果分析
     */
    public static function analyzePortfolioDiversification($asset_values) {
        $results = [];
        
        foreach ($asset_values as $asset_name => $values) {
            if (count($values) < 2) continue;
            
            $returns = [];
            for ($i = 1; $i < count($values); $i++) {
                if ($values[$i-1] > 0 && $values[$i] > 0) {
                    $return = ($values[$i] - $values[$i-1]) / $values[$i-1];
                    $returns[] = $return;
                }
            }
            
            if (!empty($returns)) {
                $volatility = self::calculateVolatility($returns);
                $results[$asset_name] = [
                    'returns' => $returns,
                    'volatility' => $volatility,
                    'risk_level' => self::classifyRiskLevel($volatility)
                ];
            }
        }
        
        return $results;
    }
    
    private static function calculateVolatility($returns) {
        if (count($returns) < 2) return 0;
        
        $mean = array_sum($returns) / count($returns);
        $variance = 0;
        
        foreach ($returns as $return) {
            $variance += pow($return - $mean, 2);
        }
        
        return sqrt($variance / (count($returns) - 1));
    }
    
    private static function classifyRiskLevel($volatility) {
        $log_vol = log10($volatility + 1e-8); // 0を避けるための小さな値を追加
        
        if ($log_vol < -2) {
            return 'very_low';
        } elseif ($log_vol < -1.5) {
            return 'low';
        } elseif ($log_vol < -1) {
            return 'medium';
        } elseif ($log_vol < -0.5) {
            return 'high';
        } else {
            return 'very_high';
        }
    }
}

// 使用例
$sample_returns = [0.02, -0.01, 0.03, -0.02, 0.01, 0.04, -0.03, 0.02];

try {
    echo "VaR分析:\n";
    $var_result = FinancialRiskAnalyzer::calculateVaR($sample_returns, 0.05, 1000000);
    echo "95%信頼水準でのVaR: " . number_format($var_result['var_amount'], 0) . "円\n";
    echo "リスク割合: " . round($var_result['var_percentage'], 2) . "%\n";
} catch (Exception $e) {
    echo "VaR計算エラー: " . $e->getMessage() . "\n";
}

// ポートフォリオ分析例
$portfolio = [
    'Stock_A' => [100, 102, 98, 105, 103, 110, 108],
    'Stock_B' => [200, 195, 205, 190, 200, 210, 205],
    'Bond_A' => [1000, 1001, 999, 1002, 1000, 1003, 1001]
];

echo "\nポートフォリオ分析:\n";
$portfolio_analysis = FinancialRiskAnalyzer::analyzePortfolioDiversification($portfolio);

foreach ($portfolio_analysis as $asset => $analysis) {
    echo "{$asset}:\n";
    echo "  ボラティリティ: " . round($analysis['volatility'], 4) . "\n";
    echo "  リスクレベル: " . $analysis['risk_level'] . "\n";
}
?>

まとめ

log10関数は、常用対数を計算する重要な数学関数で、以下のような様々な分野で活用できます:

主要な活用分野

  • 科学計算: pH値、デシベル、地震規模の計算
  • データ分析: 桁数の計算、対数スケールでの可視化
  • システム分析: ファイルサイズ、メモリ使用量の分類
  • Web解析: ページビューの規模分類、パフォーマンス分析
  • 機械学習: 特徴量変換、情報ゲインの計算
  • 金融分析: リスク評価、VaR計算

重要なポイント

  1. 入力値の検証: 正の値のみ受け付ける
  2. エラーハンドリング: 0や負の値、非数値への対処
  3. パフォーマンス: 大量データ処理時のキャッシュ活用
  4. 実用性: 対数スケールの特性を活かした分析手法

log10関数は単なる数学計算だけでなく、データの本質的な特性を理解し、効果的な分析を行うための強力なツールです。対数スケールの特性を理解して適切に活用することで、より洞察に富んだデータ処理が可能になります。


この記事がPHPでの数学計算や科学的データ処理の参考になれば幸いです。常用対数の特性を活かして、より効果的なデータ分析を実現してください。

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