Greg Hewgill dan IllidanS4 memberikan tautan dengan penjelasan matematika yang sangat baik. Saya akan mencoba merangkumnya di sini untuk mereka yang tidak ingin membahas terlalu banyak detail.
Fungsi matematika apa pun, dengan beberapa pengecualian, dapat diwakili oleh jumlah polinomial:
y = f(x)
bisa persis diubah menjadi:
y = a0 + a1*x + a2*(x^2) + a3*(x^3) + a4*(x^4) + ...
Dimana a0, a1, a2, ... adalah konstanta . Masalahnya adalah bahwa untuk banyak fungsi, seperti akar kuadrat, untuk nilai yang tepat jumlah ini memiliki jumlah anggota yang tidak terbatas, tidak berakhir pada beberapa x ^ n . Tetapi, jika kita berhenti di beberapa x ^ n kita masih akan mendapatkan hasil yang cukup presisi.
Jadi, jika kita memiliki:
y = 1/sqrt(x)
Dalam kasus khusus ini, mereka memutuskan untuk membuang semua anggota polinom di atas detik, mungkin karena kecepatan penghitungan:
y = a0 + a1*x + [...discarded...]
Dan sekarang tugasnya adalah menghitung a0 dan a1 agar y memiliki perbedaan terkecil dari nilai pastinya. Mereka telah menghitung bahwa nilai yang paling tepat adalah:
a0 = 0x5f375a86
a1 = -0.5
Jadi, saat Anda memasukkan ini ke dalam persamaan, Anda mendapatkan:
y = 0x5f375a86 - 0.5*x
Yang sama dengan baris yang Anda lihat di kode:
i = 0x5f375a86 - (i >> 1);
Sunting: sebenarnya di sini y = 0x5f375a86 - 0.5*x
tidak sama dengan i = 0x5f375a86 - (i >> 1);
karena menggeser pelampung karena bilangan bulat tidak hanya membagi dua tetapi juga membagi eksponen dua dan menyebabkan beberapa artefak lainnya, tetapi masih turun untuk menghitung beberapa koefisien a0, a1, a2 ....
Pada titik ini mereka telah menemukan bahwa ketepatan hasil ini tidak cukup untuk tujuan tersebut. Jadi mereka juga hanya melakukan satu langkah dari iterasi Newton untuk meningkatkan akurasi hasil:
x = x * (1.5f - xhalf * x * x)
Mereka bisa melakukan beberapa iterasi lagi dalam satu lingkaran, masing-masing meningkatkan hasil, sampai akurasi yang dibutuhkan terpenuhi. Inilah cara kerjanya di CPU / FPU! Tapi sepertinya hanya satu iterasi saja yang cukup, yang juga merupakan berkah untuk kecepatannya. CPU / FPU melakukan iterasi sebanyak yang diperlukan untuk mencapai akurasi angka floating point tempat hasil disimpan dan memiliki algoritme yang lebih umum yang berfungsi untuk semua kasus.
Jadi singkatnya, yang mereka lakukan adalah:
Gunakan (hampir) algoritme yang sama dengan CPU / FPU, manfaatkan peningkatan kondisi awal untuk kasus khusus 1 / sqrt (x) dan jangan menghitung sepenuhnya ke presisi CPU / FPU akan pergi tetapi berhenti lebih awal, jadi mendapatkan kecepatan kalkulasi.