Thuật toán này theo mình là một “điều kỳ diệu”. Chỉ với đúng 10 dòng code, mà trong đó, thực chất chỉ có 2 dòng thực hiện tính toán, với các phép tính đơn giản gồm phép cộng, nhân và dịch bit, thuật toán đã đưa ra một phép tính gần đúng cực kỳ hiệu quả để tính . Đây là thuật toán được xem là “chìa khóa” , dùng trong game Quake 3, để mở cánh cổng đến thế giới giả lập 3D, vào thời kỳ sơ khai khi sức mạnh tính toán còn chưa đủ mạnh.
English version here
Source Code
float Q_rsqrt(float number)
{
long i;
float x2, y;
const float threehalfs = 1.5F;
x2 = number * 0.5F;
y = number;
i = * ( long * ) &y; // evil floating point bit level hacking
i = 0x5f3759df - ( i >> 1 ); // what the fuck?
y = * ( float * ) &i;
y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration
return y;
}
Chúng ta cùng tìm hiểu thuật đoạn code trên
Chuẩn IEE754
💡 Bạn đọc có thể xem thêm chi tiết tại: Wikipedia Single-precision floating-point format
Theo như chuẩn này, một số float được dùng 32 bit để lưu trữ làm 3 phần: S – 1 bit dấu thể hiện số âm / số dương, E – 8 bit thể hiện số mũ, M – 23 bit lưu giá trị được chuẩn hóa về .
Như vậy, một biến được tính bởi công thức:
Và, thể hiện trên giá trị bit của sẽ là:
Tách thông tin nhị phân của từ
Với có giá trị nhỏ , chúng ta có thể tính xấp xỉ của thông qua công thức xấp xỉ: . Vậy:
Với bất kỳ, ta có theo (*):
Vì , ta áp dụng công thức xấp xỉ:
Lúc đó:
Tính dùng
Ý nghĩa của dòng code
i = 0x5f3759df - ( i >> 1 );
Ta có:
Đặt
Ta thay vào 2 vế của biểu diễn bit:
Đây là bí ẩn của dòng code tính toán đầu tiên.
Áp dụng Newton-Ralphson để tìm nghiệm gần đúng
Đặt , như vậy: . Để giải nghiệm cho , ta dùng phương pháp lặp Newton-Ralphson.
Đầu tiên ta đi tính đạo hàm của
Vậy, áp dụng công thức, ta có:
Và đây cũng là ý nghĩa ẩn giấu của dùng code cuối cùng:
y = y * ( threehalfs - ( x2 * y * y ) );