Greg Hewgill y IllidanS4 dio un enlace con una excelente explicación matemática. Trataré de resumirlo aquí para aquellos que no quieren profundizar en los detalles.
Cualquier función matemática, con algunas excepciones, puede ser representado por una suma polinómica:
y = f(x)
puede ser exactamente transforma en:
y = a0 + a1*x + a2*(x^2) + a3*(x^3) + a4*(x^4) + ...
Dónde a0, a1, a2 ,. .. son constantes. El problema es que para muchas funciones, como la raíz cuadrada, para el valor exacto, esta suma tiene un número infinito de miembros, no termina en unos x^n. Pero, si nos detenemos en x^n todavía tendríamos un resultado hasta cierta precisión.
lo tanto, si tenemos:
y = 1/sqrt(x)
En este caso particular se decidió descartar todos los miembros de polinomios anteriores segundos, probablemente debido a la velocidad de cálculo:
y = a0 + a1*x + [...discarded...]
Y la tarea ahora tiene vino hacia abajo para calcular a0 y a1 para que y tenga la menor diferencia con respecto al valor exacto. Ellos han calculado que los valores más adecuados son:
a0 = 0x5f375a86
a1 = -0.5
Así que cuando se pone esto en la ecuación que se obtiene:
y = 0x5f375a86 - 0.5*x
¿Qué es la misma que la línea que se ve en el código:
i = 0x5f375a86 - (i >> 1);
Editar: en realidad aquí y = 0x5f375a86 - 0.5*x
no es lo mismo que i = 0x5f375a86 - (i >> 1);
ya que el desplazamiento de flotación como un entero no solo se divide por dos sino que también divide el exponente por dos y causa algunos otros artefactos, pero aún se reduce al cálculo de algunos coeficientes a0, a1, a2 ....
En este punto han descubierto que la precisión de este resultado no es suficiente para este propósito. Así que, además, lo hicieron sólo un paso de la iteración de Newton para mejorar la precisión de los resultados:
x = x * (1.5f - xhalf * x * x)
podrían haber hecho un poco más iteraciones de un bucle, cada una mejora resultado, hasta que se cumpla la precisión requerida. ¡Así funciona exactamente en CPU/FPU! Pero parece que solo una iteración fue suficiente, lo que también fue una bendición para la velocidad. CPU/FPU realiza tantas iteraciones como sea necesario para alcanzar la precisión para el número de punto flotante en el que se almacena el resultado y tiene un algoritmo más general que funciona para todos los casos.
Así que en resumen, lo que hicieron es:
uso (casi) el mismo algoritmo que la CPU/FPU, explotar la mejora de las condiciones iniciales para el caso especial de 1/sqrt (x) y no calcule todo el camino hasta que la CPU/FPU de precisión vaya a detenerse antes, ganando velocidad de cálculo.
Esto se ha escrito sobre tropecientos millones de veces. Ver: http://www.google.com/search?q=0x5f3759df –
Gracias, sin embargo. Esta fue una pregunta mucho más interesante que "¿cómo se hace un número positivo negativo en C#?" – MusiGenesis
No era Carmack. http://en.wikipedia.org/wiki/Fast_inverse_square_root – h4xxr