PHP를 사용하여 √2

17188 단어 PHPtech

개요


구\sqrt{2}의 문제는 수치 계산에서FuzzBuzz와 비슷한 기초 문제이며, 방법은 수치 구해 f(x)=x^2-2=0이다.
이 해법은 이분법과 뉴턴법으로 유명하다.
나는 PHP를 거의 써 본 적이 없지만, 나는 이것을 연습 문제로 삼아 시험해 보고 싶다.

디자인 같은 거.


방정식을 푸는 것은 해법에 달려 있지 않을 것이다.따라서 해법 알고리즘의 실현을 인터페이스로 분리한다.
또한 예에서 f(x)=x^2-2=0이지만 PHP는 λ식을 사용할 수 있기 때문에 f(x) 자체를 매개 변수로 설정하여 통용성을 높인다.

해법에 관하여


오차가 예측 오차시간보다 많으면 이를 해결 방법의 하나로 삼는다.(이 때문에 진짜\sqrt{2}가 아니라 일정한 오차가 있다)
소개한 두 가지 방법은 간단하게 다음과 같다. 이분법은 해결 방안만 있으면 안정적으로 해결 방안을 찾을 수 있다.다른 한편, 뉴턴법은 수렴이 비교적 빠른 동시에 이해에서 멀리 떨어진 함수 시스템이 복잡할 때 때때로 방향을 향해 진동하지 않는다.

이분법


이른바 협공이란 중간에 풀린 두 개의 점이 f(x0)φ0이고 f(x1)′0의 원리를 사용하며 중점은 x이다{center]=0.5(x0+x1), f(x{center})의 기호를 통해 범위를 좁히는 방법입니다.

뉴턴법


미분을 사용하는 방법의 초기 값을 일회식 근사로 다음 해를 구하고 이 차(+함수의 값)에서 수렴하여 해를 구하는지 판단한다.

이루어지다


Solver


Solver를 방정식을 풀기 위한 도구의 인터페이스로 사용하고 매개변수는 첫 번째 매개변수를 풀 방정식을 함수 대상으로 하며 두 번째 매개변수의 초기 값으로 설정합니다.
또한 절단 오차를 솔버에 상수로 유지합니다.
이분법(By Selection)과 뉴턴법(Newton) 등급을 실현하는 것으로
내부 설치는 다음과 같습니다.
Solver.php
<?php
interface Solver{
    const threshold=1.0e-8;
    public function solve($func, $x);
}

class BySelection implements Solver{
    public function solve($func, $x){
        $x1=0.5*$x;
        $x2=1.5*$x;
        $y =$func($x);
        $y1=$func($x1);
        $y2=$func($x2);

        $count=0;
        if( $y1*$y2>0 ) throw new Exception('二分法、初期値エラー');
        while( true ){
            $count++;
            if( $y*$y1>0 ){
                $x1=$x;
                $y1=$y;
            }
            else{
                $x2=$x;
                $y2=$y;
            }
            $x=0.5*($x1+$x2);
            $y=$func($x);

            if( abs($y1)<Solver::threshold && abs($y2)<Solver::threshold && abs($x1-$x2)<Solver::threshold ) return $x;
            if( $count==1000 ) throw new Exception('二分法で収束しませんでした');
        }
    }
}

class Newton implements Solver{
    public function solve($func, $x){
        $count=0;
        while( true ){
            $count++;
            $y=$func($x);
            $dy=($func($x+Solver::threshold)-$func($x-Solver::threshold))/(2.0*Solver::threshold);

            if( abs($y)<Solver::threshold && abs($y/$dy)<Solver::threshold ) return $x;

            $x=$x-$y/$dy;
            if( $count==1000 ) throw new Exception('ニュートン法で収束しませんでした');
        }
    }
}
?>
나는 이분법이 알고리즘으로 매우 간단하기 때문에 읽을 수 있다고 생각한다.
뉴턴 방법에서 미분은 선형과 비슷하게 쓰이지만 수치 미분를 사용한다.

main 함수


실제 사용은 다음과 같다.
내부 알고리즘은 BySelection이나 뉴튼을 통해 $solver의 실체를 바꿀 수 있지만 결과는 바뀌지 않는다.
main.php
<?php
require_once('Solver.php');

// $func=function($x){ return cos($x); };
$func=function($x){ return x*x-2; };

// $sovler=new BySelection(); 
$solver=new Newton();

var_dump(2.0*$solver->solve($func, 2.0));
?>

미비


대체로 이런 구상은 가능하지만 일반적인 함수 시스템이라면 초기값 등에 따라 해결 방안을 구할 수 없을 때도 있다.(이분법의 초기값의 거친 처리 등 가장 예)
수치 계산에서 수렴조건(threshold)과 교체 횟수 등은 어느 정도 알고리즘과 해결해야 할 문제에 의존하기 때문에 흑체화는 적합하지 않다고 생각한다.

후기와 감상


필자는 PHP를 거의 사용한 적이 없다. 수치로 단일하게 이동할 수 있는 견본을 계산해 봤다. 비록 PHP가 이 용도에 적합하다고 생각하지는 않지만 인터페이스와 λ식을 사용하면 상당히 큰 대응을 할 수 있다고 생각한다.
또한 PHP의 상수 사용 방법과 예외 처리의 건너뛰기 방법(이 단계)을 알게 되었다.

참고 문헌

  • PHP: 무명 함수
  • PHP: 인터페이스
  • PHP:예외
  • 좋은 웹페이지 즐겨찾기