Алгоритм поиска n-го корня числа

Я ищу эффективный алгоритм для поиска n-го корня числа. Ответ должен быть целым числом. Я обнаружил, что метод newtons и метод bisection являются популярными методами. Существуют ли эффективные и простые методы для вывода целого числа?

4 ответов


#include <math.h>
inline int root(int input, int n)
{
  return round(pow(input, 1./n));
}

это работает практически для всего целого диапазона (как IEEE754 8-byte doubles может представлять весь 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

тот же алгоритм может быть расширен для вычисления корня алгебраического уравнения.