[알고리즘] 제곱근을 구하는 법

Eugene CHOI·2021년 4월 2일
0

Coding Test

목록 보기
4/7

Newton-Raphson Method

<math.h> 에 sqrt()함수가 있습니다. 저는 헤더파일을 사용하지 않고 제곱근 함수를 구현하고 싶기 때문에 미적분학 시간에 배우는 뉴튼-랩슨 근사법을 사용하여 제곱근을 구해보겠습니다.
뉴튼-랩슨법을 구현하는 수식은 다음과 같습니다. 사실 방향도함수를 이용한 gradient descent 알고리즘과 유사합니다. 구체적인 수학적 원리는 여기서 다루지 않으니 생략하도록 하겠습니다.

xt+1=xtf(x)f(x)x_{t+1}=x_t-\frac{f(x)}{f'(x)}

점화식을 통한 근사를 할 때, 우리가 얻고자 하는 것은 독립변수가 아니라 종속변수입니다.
지금 저희가 구하고자 하는 것은 제곱근입니다.
예를 들어 11\sqrt{11}의 근사치를 구하고 싶다고 치면, 11\sqrt{11}f(x)=x211f(x)=x^2-11의 해가 됩니다.
그럼 1111처럼 우리가 찾고 싶은 수를 kk라고 하면, 다음과 같이 정리할 수 있습니다.

f(xt)=xt2kf(x_t)=x_t^2-k
f(xt)=2xtf'(x_t)=2x_t
xt+1=xtxt2k2xtx_{t+1}=x_t-\frac{x_t^2-k}{2x_t}
xt+1=xtxt2k2xtx_{t+1}=x_t-\frac{x_t^2-k}{2x_t}
xt+1=12(xt+kxt)x_{t+1}=\frac12(x_t+\frac{k}{x_t})

최종적으로 위와 같은 식으로 나타낼 수 있습니다.

구현 예시

#include<iostream>
using namespace std;

int main(int argc, char** argv)
{
    int k = 11;
    float x = k;
    for(int i=0; i <5; i++){
        x = 0.5*(x+k/x);
        printf("%.10f\n", x);
    }
}

---------------결과----------------
6.0000000000
3.9166667461
3.3625886440
3.3169388771
3.3166246414
---------------결과----------------
적당히 5번만 진행해도 얼추 비슷해지는 모습을 확인할 수 있습니다.

사실 그 외에도 메모리를 이용한 제곱근 근사법과 같은 컴퓨터 과학적으로 접근하여 이런 반복 없이 구할 수 있는 방법이 많습니다.
그런 방법들은 제가 다룰 수 있는 영역 이상이기 때문에, 자세한 것은 여기를 참고하세요.

profile
Hi, my name is Eugene CHOI the Automotive MCU FW developer.

0개의 댓글