PHP로 구현하는 핵심 수학 알고리즘: 피보나치부터 선형 체까지

PHP는 웹 개발에서 널리 쓰이지만, 수학적 계산과 알고리즘 구현에도 충분히 활용할 수 있다. 본문에서는 대표적인 수학 알고리즘들을 PHP로 구현하는 방법을 살펴본다.

보나치 수열의 세 가지 접근법

피보나치 수열은 각 항이 앞 두 항의 합으로 정의되는 대표적인 재귀 수열이다. PHP에서는 성능과 메모리 특성에 따라 다양한 방식으로 구현할 수 있다.

재귀적 접근

가장 직관적인 구현이지만, 중복 계산으로 인해 큰 입력값에서 성능이 급격히 저하된다.

function fibRec(int $idx): int
{
    if ($idx < 2) {
        return $idx;
    }
    return fibRec($idx - 1) + fibRec($idx - 2);
}

반복적 접근

변수 두 개를 활용해 중간 결과를 저장하며 반복, O(n) 시간 복잡도로 해결한다.

function fibLoop(int $idx): int
{
    if ($idx < 2) {
        return $idx;
    }
    
    $prev2 = 0;
    $prev1 = 1;
    $current = 0;
    
    for ($i = 2; $i <= $idx; $i++) {
        $current = $prev1 + $prev2;
        $prev2 = $prev1;
        $prev1 = $current;
    }
    
    return $current;
}

Generator를 활용한 메모리 절약

대량의 수열 항을 순회해야 할 때 Generator를 사용하면 메모리를 상수 공간으로 제한할 수 있다.

function fibStream(int $terms): Generator
{
    $left = 0;
    $right = 1;
    
    for ($k = 0; $k < $terms; $k++) {
        yield $left;
        $sum = $left + $right;
        $left = $right;
        $right = $sum;
    }
}

소수 판별과 선형 체(Linear Sieve)

기본 소수 판정법

2부터 √n까지 나누어보는 방식. n < 2일 때를 먼저 처리하는 것이 핵심이다.

function checkPrime(int $candidate): bool
{
    if ($candidate < 2) {
        return false;
    }
    if ($candidate === 2) {
        return true;
    }
    if ($candidate % 2 === 0) {
        return false;
    }
    
    $bound = (int)sqrt($candidate);
    for ($divisor = 3; $divisor <= $bound; $divisor += 2) {
        if ($candidate % $divisor === 0) {
            return false;
        }
    }
    return true;
}

선형 체: 빠른 소수 생성

에라토스테네스의 체를 개선한 선형 체는 각 합성수를 그 최소 소인수로만 한 번씩 제거해 O(n) 시간 복잡도를 달성한다.

function linearSieve(int $max): array
{
    $isComposite = array_fill(0, $max + 1, false);
    $primes = [];
    
    for ($num = 2; $num <= $max; $num++) {
        if (!$isComposite[$num]) {
            $primes[] = $num;
        }
        
        foreach ($primes as $p) {
            if ($num * $p > $max) {
                break;
            }
            $isComposite[$num * $p] = true;
            if ($num % $p === 0) {
                break;
            }
        }
    }
    
    return $primes;
}

활용 수학 알고리즘

팩토리얼과 예외 처리

function computeFactorial(int $n): int
{
    if ($n < 0) {
        throw new InvalidArgumentException("음수에 대해서는 팩토리얼을 정의하지 않는다");
    }
    
    $result = 1;
    for ($m = 2; $m <= $n; $m++) {
        $result *= $m;
    }
    return $result;
}

유클리드 호제법

function euclideanGcd(int $x, int $y): int
{
    while ($y !== 0) {
        $remainder = $x % $y;
        $x = $y;
        $y = $remainder;
    }
    return abs($x);
}

팰린드롬 수 판별

function isPalindromeNumber(int $value): bool
{
    if ($value < 0) {
        return false;
    }
    
    $original = $value;
    $reversed = 0;
    
    while ($value > 0) {
        $reversed = $reversed * 10 + ($value % 10);
        $value = (int)($value / 10);
    }
    
    return $original === $reversed;
}

실전 적용 예시

Generator 기반 피보나치를 실제 코드에서 활용하는 모습:

$sequence = fibStream(50);

foreach ($sequence as $index => $fibValue) {
    printf("F(%d) = %d\n", $index, $fibValue);
}

선형 체를 이용한 대량 소수 필터링:

$allPrimes = linearSieve(1000000);
$twinPrimes = [];

for ($i = 0; $i < count($allPrimes) - 1; $i++) {
    if ($allPrimes[$i + 1] - $allPrimes[$i] === 2) {
        $twinPrimes[] = [$allPrimes[$i], $allPrimes[$i + 1]];
    }
}

printf("100만 이하 쌍둥이 소수 쌍의 개수: %d\n", count($twinPrimes));

태그: PHP 수학 알고리즘 피보나치 수열 에라토스테네스의 체 선형 체

6월 3일 18:41에 게시됨