Алгоритм поиска n-го корня числа
Я ищу эффективный алгоритм для поиска n-го корня числа. Ответ должен быть целым числом. Я обнаружил, что метод newtons и метод bisection являются популярными методами. Существуют ли эффективные и простые методы для вывода целого числа?
4 ответов
#include <math.h>
inline int root(int input, int n)
{
return round(pow(input, 1./n));
}
это работает практически для всего целого диапазона (как IEEE754 8-byte double
s может представлять весь 32-бит int
диапазон точно, которые являются представлениями и размерами, которые используются практически в каждой системе). И я сомневаюсь, что любой алгоритм на основе целого числа быстрее на не-Древнем оборудовании. Включая руку. Встроенные контроллеры (вид микроволновой стиральной машины) могут не иметь оборудования с плавающей запятой. Но эта часть вопроса была недооценена.
Я знаю, что этот поток, вероятно, мертв, но я не вижу никаких ответов, которые мне нравятся, и это меня беспокоит...
int root(int a, int n) {
int v = 1, bit, tp, t;
if (n == 0) return 0; //error: zeroth root is indeterminate!
if (n == 1) return a;
tp = iPow(v,n);
while (tp < a) { // first power of two such that v**n >= a
v <<= 1;
tp = iPow(v,n);
}
if (tp == a) return v; // answer is a power of two
v >>= 1;
bit = v >> 1;
tp = iPow(v, n); // v is highest power of two such that v**n < a
while (a > tp) {
v += bit; // add bit to value
t = iPow(v, n);
if (t > a) v -= bit; // did we add too much?
else tp = t;
if ( (bit >>= 1) == 0) break;
}
return v; // closest integer such that v**n <= a
}
// used by root function...
int iPow(int a, int e) {
int r = 1;
if (e == 0) return r;
while (e != 0) {
if ((e & 1) == 1) r *= a;
e >>= 1;
a *= a;
}
return r;
}
этот метод также будет работать с математикой фиксированной точки произвольной точности, если вы хотите вычислить что-то вроде sqrt(2) до 100 знаков после запятой...
Я сомневаюсь в вашем использовании "алгоритм" когда речь идет о программы C. Программы и алгоритмы не одинаковы (алгоритм математический; ожидается, что программа C будет реализация какой-то алгоритм).
но на текущих процессорах (например, в последних ноутбуках x86-64 или настольных компьютерах)FPU делает достаточно хорошо. Я предполагаю (но не тестировал), что быстрый способ вычисления n-го корня может быть,
inline unsigned root(unsigned x, unsigned n) {
switch (n) {
case 0: return 1;
case 1: return x;
case 2: return (unsigned)sqrt((double)x);
case 3: return (unsigned)cbrt((double)x);
default: return (unsigned) pow (x, 1.0/n);
}
}
(Я сделал переключатель, потому что у многих процессоров есть оборудование для вычисления sqrt
и у некоторых есть оборудование для вычисления cbrt
..., поэтому вы должны предпочесть это, когда это уместно...).
Я не уверен, что корень N-й степени из отрицательного числа имеет смысл в целом. Так что мой root
функция принимает некоторые unsigned x
и возвращает часть unsigned
количество.
для самого быстрого n-го корневого алгоритма с помощью ведической математики См. http://www.slideshare.net/jadhavvitthal1989/vjs-root-algorithm-final
тот же алгоритм может быть расширен для вычисления корня алгебраического уравнения.