Подтвердить что ты не робот

Быстрая оптимизация квадратного корня?

Если вы проверите эту очень приятную страницу:

http://www.codeproject.com/Articles/69941/Best-Square-Root-Method-Algorithm-Function-Precisi

Вы увидите эту программу:

#define SQRT_MAGIC_F 0x5f3759df 
 float  sqrt2(const float x)
{
  const float xhalf = 0.5f*x;

  union // get bits for floating value
  {
    float x;
    int i;
  } u;
  u.x = x;
  u.i = SQRT_MAGIC_F - (u.i >> 1);  // gives initial guess y0
  return x*u.x*(1.5f - xhalf*u.x*u.x);// Newton step, repeating increases accuracy 
}

Мой вопрос: есть ли какая-то особая причина, почему это не реализовано как:

#define SQRT_MAGIC_F 0x5f3759df 
 float  sqrt2(const float x)
{

  union // get bits for floating value
  {
    float x;
    int i;
  } u;
  u.x = x;
  u.i = SQRT_MAGIC_F - (u.i >> 1);  // gives initial guess y0

  const float xux = x*u.x;

  return xux*(1.5f - .5f*xux*u.x);// Newton step, repeating increases accuracy 
}

Как, из разборки, я вижу меньше MUL. Есть ли какая-либо цель иметь xhalf вообще?

4b9b3361

Ответ 1

Может быть, что унаследованная математика с плавающей запятой, которая использовала 80-битные регистры, была более точной, когда множители, которые были связаны вместе в последней строке в качестве промежуточных результатов, где хранились в 80-битных регистрах.

Первое умножение в верхней реализации происходит параллельно с следующей целочисленной математикой, они используют разные ресурсы выполнения. Вторая функция, с другой стороны, выглядит быстрее, но трудно сказать, действительно ли это из-за вышеизложенного. Кроме того, оператор const float xux = x * u.x; уменьшает результат до 32-битного поплавка, что может снизить общую точность.

Вы можете проверить эти функции на голову и сравнить их с функцией sqrt в math.h(используйте double not float). Таким образом, вы можете видеть, что быстрее, а точнее.