[PHP]is_infinite関数の使い方と実例解説|無限値判定の完全ガイド

PHP

PHPで数値計算を行う際、計算結果が無限大(infinity)になることがあります。このような無限値を適切に検出し処理するために使用されるのがis_infinite()関数です。この記事では、is_infinite()関数の基本的な使い方から実践的な活用法まで、詳しく解説していきます。

is_infinite関数とは?

is_infinite()は、指定された値が無限大(正の無限大または負の無限大)かどうかを判定するPHPの組み込み関数です。数値計算でオーバーフローが発生した場合や、ゼロ除算が行われた場合などに発生する無限値を検出できます。

基本的な構文

is_infinite(float $value): bool
  • 引数: $value – 判定したい値(float型)
  • 戻り値: 無限値の場合はtrue、有限値やNaNの場合はfalse

具体的な使用例

基本的な使用例

<?php
// 正の無限大
var_dump(is_infinite(INF));         // bool(true)
var_dump(is_infinite(1/0));         // bool(true)

// 負の無限大
var_dump(is_infinite(-INF));        // bool(true)
var_dump(is_infinite(-1/0));        // bool(true)

// 有限値
var_dump(is_infinite(42));          // bool(false)
var_dump(is_infinite(3.14));        // bool(false)
var_dump(is_infinite(-10.5));       // bool(false)

// NaN(Not a Number)
var_dump(is_infinite(NAN));         // bool(false)
var_dump(is_infinite(0/0));         // bool(false)
?>

計算結果の検証

<?php
function safeDivision($numerator, $denominator) {
    $result = $numerator / $denominator;
    
    if (is_infinite($result)) {
        if ($result > 0) {
            return "正の無限大";
        } else {
            return "負の無限大";
        }
    } elseif (is_nan($result)) {
        return "計算不可能(NaN)";
    } else {
        return $result;
    }
}

echo safeDivision(10, 2);   // 5
echo safeDivision(10, 0);   // 正の無限大
echo safeDivision(-10, 0);  // 負の無限大
echo safeDivision(0, 0);    // 計算不可能(NaN)
?>

実践的な活用場面

1. 数学的計算の安全性チェック

<?php
function calculateGrowthRate($initialValue, $finalValue, $periods) {
    if ($periods <= 0) {
        throw new InvalidArgumentException("期間は正の数である必要があります");
    }
    
    if ($initialValue == 0) {
        throw new InvalidArgumentException("初期値は0にできません");
    }
    
    $growthRate = pow(($finalValue / $initialValue), (1 / $periods)) - 1;
    
    if (is_infinite($growthRate)) {
        throw new OverflowException("成長率の計算で無限値が発生しました");
    }
    
    return $growthRate;
}

try {
    $rate = calculateGrowthRate(100, 200, 5);
    echo "成長率: " . ($rate * 100) . "%";
} catch (Exception $e) {
    echo "エラー: " . $e->getMessage();
}
?>

2. 統計計算での無限値処理

<?php
class StatisticsCalculator {
    public static function calculateZScore($value, $mean, $stdDev) {
        if ($stdDev == 0) {
            throw new InvalidArgumentException("標準偏差は0にできません");
        }
        
        $zScore = ($value - $mean) / $stdDev;
        
        if (is_infinite($zScore)) {
            return null; // 無限値の場合はnullを返す
        }
        
        return $zScore;
    }
    
    public static function processDataSet($data) {
        $mean = array_sum($data) / count($data);
        $variance = 0;
        
        foreach ($data as $value) {
            $variance += pow($value - $mean, 2);
        }
        $stdDev = sqrt($variance / count($data));
        
        $zScores = [];
        foreach ($data as $value) {
            $zScore = self::calculateZScore($value, $mean, $stdDev);
            if ($zScore !== null && !is_infinite($zScore)) {
                $zScores[] = $zScore;
            }
        }
        
        return $zScores;
    }
}

// 使用例
$dataset = [10, 20, 30, 40, 50];
$zScores = StatisticsCalculator::processDataSet($dataset);
print_r($zScores);
?>

3. APIレスポンスの検証とクリーニング

<?php
function validateAndCleanNumericData($apiResponse) {
    $cleanedData = [];
    
    foreach ($apiResponse as $key => $value) {
        if (is_numeric($value)) {
            $floatValue = (float)$value;
            
            if (is_infinite($floatValue)) {
                // 無限値の場合は適切なデフォルト値を設定
                $cleanedData[$key] = [
                    'value' => null,
                    'status' => 'infinite',
                    'original' => $value
                ];
            } elseif (is_nan($floatValue)) {
                $cleanedData[$key] = [
                    'value' => null,
                    'status' => 'nan',
                    'original' => $value
                ];
            } else {
                $cleanedData[$key] = [
                    'value' => $floatValue,
                    'status' => 'valid',
                    'original' => $value
                ];
            }
        } else {
            $cleanedData[$key] = [
                'value' => null,
                'status' => 'invalid',
                'original' => $value
            ];
        }
    }
    
    return $cleanedData;
}

// 使用例
$apiData = [
    'temperature' => '25.5',
    'humidity' => 'INF',
    'pressure' => '-INF',
    'windSpeed' => 'NAN',
    'visibility' => '10.0'
];

$cleanedData = validateAndCleanNumericData($apiData);
foreach ($cleanedData as $key => $data) {
    echo "{$key}: {$data['status']} (value: {$data['value']})\n";
}
?>

無限値の種類と判定

正の無限大と負の無限大の区別

<?php
function analyzeInfinity($value) {
    if (is_infinite($value)) {
        if ($value > 0) {
            return "正の無限大 (+∞)";
        } else {
            return "負の無限大 (-∞)";
        }
    } else {
        return "有限値または非数値";
    }
}

// テスト
$testValues = [INF, -INF, 1/0, -1/0, 42, NAN];
foreach ($testValues as $value) {
    echo "値: " . var_export($value, true) . " → " . analyzeInfinity($value) . "\n";
}
?>

無限値の生成パターン

<?php
function demonstrateInfinityCreation() {
    $examples = [
        'ゼロ除算(正)' => 1/0,
        'ゼロ除算(負)' => -1/0,
        '大きすぎる数値' => pow(10, 400),
        'log(0)' => log(0),
        'INF定数' => INF,
        '-INF定数' => -INF,
        'INF + 1' => INF + 1,
        'INF * 2' => INF * 2
    ];
    
    foreach ($examples as $description => $value) {
        printf("%-20s: %s (is_infinite: %s)\n", 
            $description, 
            var_export($value, true),
            is_infinite($value) ? 'true' : 'false'
        );
    }
}

demonstrateInfinityCreation();
?>

類似関数との比較と使い分け

is_infinite() vs is_finite() vs is_nan()

<?php
function compareNumericFunctions() {
    $testValues = [42, 3.14, INF, -INF, NAN, 0, '123'];
    
    echo "値\t\tis_infinite\tis_finite\tis_nan\n";
    echo str_repeat("-", 50) . "\n";
    
    foreach ($testValues as $value) {
        printf("%-10s\t%-10s\t%-10s\t%-10s\n",
            var_export($value, true),
            is_infinite($value) ? 'true' : 'false',
            is_finite($value) ? 'true' : 'false',
            is_nan($value) ? 'true' : 'false'
        );
    }
}

compareNumericFunctions();
?>

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

数値状態判定クラス

<?php
class NumericValidator {
    const STATUS_FINITE = 'finite';
    const STATUS_POSITIVE_INFINITE = 'positive_infinite';
    const STATUS_NEGATIVE_INFINITE = 'negative_infinite';
    const STATUS_NAN = 'nan';
    const STATUS_INVALID = 'invalid';
    
    public static function analyzeNumber($value) {
        if (!is_numeric($value)) {
            return self::STATUS_INVALID;
        }
        
        $floatValue = (float)$value;
        
        if (is_nan($floatValue)) {
            return self::STATUS_NAN;
        }
        
        if (is_infinite($floatValue)) {
            return $floatValue > 0 ? self::STATUS_POSITIVE_INFINITE : self::STATUS_NEGATIVE_INFINITE;
        }
        
        return self::STATUS_FINITE;
    }
    
    public static function isCalculationSafe($value) {
        $status = self::analyzeNumber($value);
        return $status === self::STATUS_FINITE;
    }
    
    public static function sanitizeNumber($value, $defaultValue = 0) {
        if (self::isCalculationSafe($value)) {
            return (float)$value;
        }
        return $defaultValue;
    }
}

// 使用例
$testValues = [42, INF, -INF, NAN, '123', 'abc'];
foreach ($testValues as $value) {
    $status = NumericValidator::analyzeNumber($value);
    $safe = NumericValidator::isCalculationSafe($value);
    $sanitized = NumericValidator::sanitizeNumber($value, 999);
    
    echo "値: " . var_export($value, true) . 
         " → 状態: {$status}, 安全: " . ($safe ? 'Yes' : 'No') . 
         ", 正規化: {$sanitized}\n";
}
?>

エラーハンドリングとログ出力

無限値検出時の適切な処理

<?php
class CalculationLogger {
    private static $logFile = 'calculation_errors.log';
    
    public static function logInfinityError($operation, $operands, $result) {
        $message = sprintf(
            "[%s] 無限値検出 - 演算: %s, オペランド: %s, 結果: %s",
            date('Y-m-d H:i:s'),
            $operation,
            json_encode($operands),
            var_export($result, true)
        );
        
        error_log($message . "\n", 3, self::$logFile);
    }
    
    public static function safeCalculation($callback, $operands, $operationName) {
        try {
            $result = call_user_func_array($callback, $operands);
            
            if (is_infinite($result)) {
                self::logInfinityError($operationName, $operands, $result);
                throw new OverflowException("計算結果が無限値になりました: {$operationName}");
            }
            
            return $result;
        } catch (Exception $e) {
            self::logInfinityError($operationName, $operands, $e->getMessage());
            throw $e;
        }
    }
}

// 使用例
try {
    $result = CalculationLogger::safeCalculation(
        function($a, $b) { return $a / $b; },
        [10, 0],
        'division'
    );
    echo "結果: {$result}";
} catch (Exception $e) {
    echo "エラー: " . $e->getMessage();
}
?>

パフォーマンスと最適化

大量データ処理時の効率的な実装

<?php
function filterInfiniteValues(array $data): array {
    return array_filter($data, function($value) {
        return is_numeric($value) && !is_infinite((float)$value);
    });
}

function countInfiniteValues(array $data): array {
    $counts = [
        'finite' => 0,
        'positive_infinite' => 0,
        'negative_infinite' => 0,
        'nan' => 0,
        'invalid' => 0
    ];
    
    foreach ($data as $value) {
        if (!is_numeric($value)) {
            $counts['invalid']++;
        } else {
            $floatValue = (float)$value;
            if (is_nan($floatValue)) {
                $counts['nan']++;
            } elseif (is_infinite($floatValue)) {
                $counts[$floatValue > 0 ? 'positive_infinite' : 'negative_infinite']++;
            } else {
                $counts['finite']++;
            }
        }
    }
    
    return $counts;
}

// 使用例
$largeDataset = [1, 2, INF, 3, -INF, NAN, 4, 5, 'invalid', 6];
$cleanData = filterInfiniteValues($largeDataset);
$statistics = countInfiniteValues($largeDataset);

echo "元のデータ数: " . count($largeDataset) . "\n";
echo "有効なデータ数: " . count($cleanData) . "\n";
print_r($statistics);
?>

まとめ

is_infinite()関数は、PHPで数値計算における無限値を検出する重要な関数です。主な活用場面は以下の通りです:

  • 数学的計算の検証: 除算やべき乗計算で発生する無限値の検出
  • データ検証: APIレスポンスやユーザー入力の無限値チェック
  • エラーハンドリング: 計算エラーの適切な処理
  • 統計処理: 大量データから無効な値の除外
  • ログ出力: 計算異常の記録と分析

is_finite()is_nan()と組み合わせることで、より堅牢な数値処理システムを構築できます。無限値が発生する可能性がある数値計算では、積極的にis_infinite()を活用して安全性を確保しましょう。

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