Я разочарован тем, что великие старые математические уловки, похоже, теряются. Вот ответ, который вы просите. Источник - отличный веб-сайт Пола Се: http://www.azillionmonkeys.com/qed/sqroot.html. Обратите внимание, что вы не заботитесь о расстоянии; Вы сделаете хорошо для своего рода с квадратом расстояния, который будет намного быстрее.
В 2D мы можем получить грубое приближение метрики расстояния без квадратного корня по формуле:
distanceapprox (x, y) = (1 + 1 / (4-2 * √2)) / 2 * min ((1 / √2) * (| x | + | y |), не более (| x |, | y |)) http://i52.tinypic.com/280tbnc.gif
, который будет отклоняться от истинного ответа максимум на 8%. Аналогичный вывод для 3-х измерений приводит к:
distanceapprox (x, y, z) = (1 + 1 / 4√3) / 2 * min ((1 / √3) * (| x | + | y | + | z |), max (| x |, | y |, | z |)) http://i53.tinypic.com/2vlphz8.gif
с максимальной ошибкой около 16%.
Однако следует отметить, что зачастую это расстояние требуется только для сравнения. Например, при вычислении классического множества Мандельброта (z ← z2 + c) величина комплексного числа обычно сравнивается с длиной радиуса границы 2. В этих случаях можно просто отбросить квадратный корень, по сути возводя в квадрат оба стороны сравнения (так как расстояния всегда неотрицательны). То есть:
√(Δx2+Δy2) < d is equivalent to Δx2+Δy2 < d2, if d ≥ 0
Я должен также упомянуть, что в главе 13.2 «Понимания цифровой обработки сигналов» Ричарда Г. Лайонса имеется невероятная коллекция двухмерных алгоритмов расстояния (например, аппроксимации величин комплексных чисел). В качестве одного примера:
Макс = х> у? х: у;
Мин = х <у? х: у; </p>
if (Мин. <0,04142135Макс.) </p>
|V| = 0.99 * Max + 0.197 * Min;
еще
|V| = 0.84 * Max + 0.561 * Min;
с максимальной ошибкой 1,0% от фактического расстояния. Наказанием, конечно, является то, что вы делаете пару ветвей; но даже у «самого принятого» ответа на этот вопрос есть по крайней мере три ветви.
Если вы серьезно относитесь к супербыстрой оценке расстояния с определенной точностью, вы можете сделать это, написав свою собственную упрощенную оценку fsqrt (), используя тот же базовый метод, что и поставщики компиляторов, но с меньшей точностью, делая фиксированное количество итераций. Например, вы можете исключить обработку специального случая для чрезвычайно малых или больших чисел и / или уменьшить количество итераций Ньютона-Рафесона. Это была ключевая стратегия, лежащая в основе так называемой реализации Quake 3 быстрый обратный квадратный корень - это классический алгоритм Ньютона с ровно одной итерацией.
Не думайте, что ваша реализация fsqrt () работает медленно, не сравнивая ее и / или читая исходники. Большинство современных реализаций библиотеки fsqrt () работают без ветвей и очень быстро. Вот, например, старая реализация IBM с плавающей точкой fsqrt. Преждевременная оптимизация является и всегда будет корнем всего зла.