Coding/CPP 삽질기2023. 2. 26. 20:08

요즘 핫 한 ChatGPT를 유료 결제 하고, 이것 저것 질문을 해보았습니다.

Q) please explain about the John Carmack's q_sqrt function as Korean

A) 존 카맥의 q_sqrt 함수는 양의 부동 소수점 수에 대한 빠른 제곱근 근사치 함수입니다. 이 함수는 제한된 범위의 입력에 대해 빠르고 정확하게 작동하도록 설계되었습니다.

다음은 q_sqrt 함수의 C 코드입니다:

float q_sqrt(float x) {
    int i = *(int *)&x;
    i = 0x1fbd1df5 + (i >> 1);
    return *(float *)&i;
}

q_sqrt 함수는 x라는 하나의 인자를 취합니다. 이 인자는 우리가 제곱근을 계산하려는 양의 부동 소수점 수입니다. 함수는 x의 근삿값인 제곱근을 반환합니다.

함수는 먼저 포인터 캐스트를 사용하여 float 인자를 int로 변환합니다. 그런 다음 부동 소수점 수의 정수 표현은 하나의 비트만큼 오른쪽으로 시프트됩니다.

그 다음 0x1fbd1df5라는 정수 값이 오른쪽으로 시프트된 정수 값에 더해집니다. 이 값은 제곱근 함수의 근사치를 제한된 범위의 입력에 대해 얻기 위해 선택된 매직 상수입니다. 덧셈의 결과는 포인터 캐스트를 사용하여 다시 float로 변환되고 반환됩니다.

q_sqrt 함수는 [0, 2^30] 범위의 입력에 대해 빠르고 정확합니다. 그러나 입력이 커질수록 정확도가 낮아집니다. 이 함수는 표준 라이브러리의 sqrt 함수보다 정확도가 떨어지지만 더 빠르며 근사 오차는 여전히 많은 응용 프로그램에 충분히 작습니다.


  ChatGPT 가 알려준 코드는 매우 잘 돌아가는데, 코드가 이해가 가지 않아서, 이리 저리 구글링을 해보았다.

 먼저 그 유명한, 존 카맥의 고속 역 제곱근을 코드를 보고,  

https://ko.wikipedia.org/wiki/%EA%B3%A0%EC%86%8D_%EC%97%AD_%EC%A0%9C%EA%B3%B1%EA%B7%BC

 

고속 역 제곱근 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 고속 역 제곱근(高速逆-根, fast inverse square root)은 때때로 Fast InvSqrt()나 16진수 0x5f3759df라고도 하는, IEEE 754 부동소수점 체계의 32비트 실수에 대한 제곱근의 역

ko.wikipedia.org

아래와 같은 방식으로  sqrt(x)를 구할 수 있다는 것을 알 수 있다.

그래서 아래와 같은 코드가 나오게 됩니다.

 i = 0x1fbd1df5 + (i >> 1);

그럼 이 코드를 실행 보면,

#include <iostream>

float q_sqrt(float x) {
    int i = *(int *)&x;
    i = 0x1fbd1df5 + (i >> 1);
    return *(float *)&i;
}

float q_sqrt_new_magic_number(float x) {
    int i = *(int *)&x;
    i = 0x1fbd3ee7 + (i >> 1);
    return *(float *)&i;
}


int main(int argc, char **argv) {
    std::cout << q_sqrt(9) << std::endl;
    std::cout << q_sqrt_new_magic_number(9) << std::endl;
    return 0;
}

존 카맥 형님의 매직 넘버를 사용한게 오차률이 낮습니다. ㅠㅜ

결론:   ChatGPT가 똑똑 합니다.


 

 

'Coding > CPP 삽질기' 카테고리의 다른 글

프로그래머스 사이트 기초 문제 풀기  (0) 2023.06.07
별 그리기  (0) 2021.06.08
Stack과 Heap  (0) 2021.02.25
Posted by chobocho