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計算
重要なポイント
- 入力値の検証: 正の値のみ受け付ける
- エラーハンドリング: 0や負の値、非数値への対処
- パフォーマンス: 大量データ処理時のキャッシュ活用
- 実用性: 対数スケールの特性を活かした分析手法
log10
関数は単なる数学計算だけでなく、データの本質的な特性を理解し、効果的な分析を行うための強力なツールです。対数スケールの特性を理解して適切に活用することで、より洞察に富んだデータ処理が可能になります。
この記事がPHPでの数学計算や科学的データ処理の参考になれば幸いです。常用対数の特性を活かして、より効果的なデータ分析を実現してください。