분명히 퀘이크 게임을 거슬러 올라가는 역 제곱근을 계산하는 "마법"방법은 많은 출처에서 설명됩니다. 위키 백과는 그것에 좋은 기사가 있습니다 https://cs.uwaterloo.ca/~m32rober/rsqrt.pdf지진 역 제곱근 : 정확도
나는이 논문에서 이러한 결과의 일부를 복제하기 위해 노력하고있어 : 내가 특히 발견 https://en.wikipedia.org/wiki/Fast_inverse_square_root
을 알고리즘의 아주 좋은 쓰기 업 및 분석을 할 다음 ,하지만 정확성에 문제가 있습니다. 다음 C 코딩 알고리즘은, 주어진다
#include <math.h>
#include <stdio.h>
float Q_rsqrt(float number) {
long i;
float x2, y;
const float threehalfs = 1.5F;
x2 = number * 0.5F;
y = number;
i = *(long *) &y;
i = 0x5f3759df - (i >> 1);
y = *(float *) &i;
y = y * (threehalfs - (x2 * y * y));
// y = y * (threehalfs - (x2 * y * y));
return y;
}
paper 상태 상대 오차가 모두 양의 정상 수레 0.0017522874
많아야된다. (. 코드, 및 1.4 절에서 논의 부록 2 참조)
그러나, 나는 "플러그인"때 숫자 1.4569335e-2F
, 내가 얻을 오류가이보다 큰 예측 오차 :
int main()
{
float f = 1.4569335e-2F;
double tolerance = 0.0017522874;
double actual = 1.0/sqrt(f);
float magic = Q_rsqrt(f);
double err = fabs (sqrt(f) * (double) magic - 1);
printf("Input : %a\n", f);
printf("Actual : %a\n", actual);
printf("Magic : %a\n", magic);
printf("Err : %a\n", err);
printf("Tolerance: %a\n", tolerance);
printf("Passes : %d\n", err <= tolerance);
return 0;
}
출력은 :
Input : 0x1.dd687p-7
Actual : 0x1.091cc953ea828p+3
Magic : 0x1.08a5dcp+3
Err : 0x1.cb5b716b7b6p-10
Tolerance: 0x1.cb5a044e0581p-10
Passes : 0
그래서, 이러한 특정 입력은 종이로 이루어지는 제 위배 보인다.
이것이 용지 자체에 문제가 있는지 또는 코딩 과정에서 실수를 한 것인지 궁금합니다. 나는 어떤 의견을 주셔서 감사합니다!
[paper] (https://cs.uwaterloo.ca/~m32rober/rsqrt.pdf), 부록 A.2를 보면 샘플링을 통해 최대 오차가 계산됩니다. 그러므로, 나는 최대 에러보다 약간 큰 에러를 찾기가 너무 걱정되지 않을 것이다 ... – francis
@francis 그렇지 않다. 프로그램은 0x00800000에서 0x7f7fffff까지의 모든 32 비트 값을 테스트합니다.이 값은 거의 모든 양수 float 값 범위를 포함합니다. –
@francis가 맞다고 생각합니다. 여기서 샘플링이 문제입니다. 진술 된 상대적인 오류는 Quake에서 사용 된 원래의 마법 번호에 적용됩니다. (즉, 문제는 실제로 원래의 마법 번호와 관련된 상대적인 오류에 관한 것이지 그 이상의 개선은 아닙니다.) –