95

I'm trying to get the nth root of a number using JavaScript, but I don't see a way to do it using the built in Math object. Am I overlooking something?
If not...

Is there a math library I can use that has this functionality?
If not...

What's the best algorithm to do this myself?

Nathan
  • 6,446
  • 9
  • 36
  • 54
  • How many of the roots do you want? Just the single most obvious, or all of them? – Ignacio Vazquez-Abrams Sep 05 '11 at 13:19
  • 1
    the obvious answers using Math.pow(x, 1/n) are down below the most upwards ones here - which I don't understand, because these homebaked algos dont offer anything new over the Math.pow usage. Also, for any n-th root that is multiple of 2 or 3 you can use Math.sqrt or Math.cbrt (which ananswer below mentions already), and chain-call them n times to get any 2^n or 3^n -th root (with n >= 1 obviously). or any other factorization, like the 6-th root would be the Math.sqrt(Math.cbrt(x)) for example (or the other way round, it doesnt matter). – Tchakabam Dec 05 '21 at 06:05

9 Answers9

177

Can you use something like this?

Math.pow(n, 1/root);

eg.

Math.pow(25, 1/2) == 5
Digital Plane
  • 35,904
  • 7
  • 55
  • 59
  • 1
    This will work if the pow function can take a fractional exponent. Not sure, but it _should_ :) – Richard H Sep 05 '11 at 13:18
  • 2
    it does but does not handle negative numbers – mplungjan Sep 05 '11 at 13:39
  • 2
    A small note. The pow function approximates the answer. So, for large values, this approximation can return very wrong numbers. [[reference](http://stackoverflow.com/questions/9956471/wrong-result-by-java-math-pow)]. The same is true for the JS implementation. [ref](http://www.ecma-international.org/ecma-262/6.0/#sec-math.pow) – Debosmit Ray Mar 13 '16 at 09:03
  • 2
    How to handle `Math.pow(-32, 1/5)`? – Qian Chen Dec 13 '18 at 21:03
  • 1
    @QianChen Always make the *base* be positive (-32 ➜ 32). Then, if the *exponent* is odd (5, so yes), turn the *result* negative (2 ➜ -2) – Gust van de Wal May 06 '21 at 18:14
28

The nth root of x is the same as x to the power of 1/n. You can simply use Math.pow:

var original = 1000;
var fourthRoot = Math.pow(original, 1/4);
original == Math.pow(fourthRoot, 4); // (ignoring floating-point error)
Jeremy
  • 1
  • 83
  • 335
  • 359
14

Use Math.pow()

Note that it does not handle negative nicely - here is a discussion and some code that does

http://cwestblog.com/2011/05/06/cube-root-an-beyond/

function nthroot(x, n) {
  try {
    var negate = n % 2 == 1 && x < 0;
    if(negate)
      x = -x;
    var possible = Math.pow(x, 1 / n);
    n = Math.pow(possible, n);
    if(Math.abs(x - n) < 1 && (x > 0 == n > 0))
      return negate ? -possible : possible;
  } catch(e){}
}
Sphinxxx
  • 11,400
  • 4
  • 49
  • 78
mplungjan
  • 155,085
  • 27
  • 166
  • 222
11

You could use

Math.nthroot = function(x,n) {
    //if x is negative function returns NaN
    return this.exp((1/n)*this.log(x));
}
//call using Math.nthroot();
Somebody
  • 333
  • 3
  • 11
6

For the special cases of square and cubic root, it's best to use the native functions Math.sqrt and Math.cbrt respectively.

As of ES7, the exponentiation operator ** can be used to calculate the nth root as the 1/nth power of a non-negative base:

let root1 = Math.PI ** (1 / 3); // cube root of π

let root2 = 81 ** 0.25;         // 4th root of 81

This doesn't work with negative bases, though.

let root3 = (-32) ** 5;         // NaN
GOTO 0
  • 35,223
  • 20
  • 108
  • 138
5

The n-th root of x is a number r such that r to the power of 1/n is x.

In real numbers, there are some subcases:

  • There are two solutions (same value with opposite sign) when x is positive and r is even.
  • There is one positive solution when x is positive and r is odd.
  • There is one negative solution when x is negative and r is odd.
  • There is no solution when x is negative and r is even.

Since Math.pow doesn't like a negative base with a non-integer exponent, you can use

function nthRoot(x, n) {
  if(x < 0 && n%2 != 1) return NaN; // Not well defined
  return (x < 0 ? -1 : 1) * Math.pow(Math.abs(x), 1/n);
}

Examples:

nthRoot(+4, 2); // 2 (the positive is chosen, but -2 is a solution too)
nthRoot(+8, 3); // 2 (this is the only solution)
nthRoot(-8, 3); // -2 (this is the only solution)
nthRoot(-4, 2); // NaN (there is no solution)
Oriol
  • 249,902
  • 55
  • 405
  • 483
  • "nthRoot(-4, 2); // NaN (there is no solution)" well... at least not in real numbers – Moritz Feb 14 '17 at 17:06
  • After seeing https://stackoverflow.com/a/46268374/205696 I found a few optimizations to `nthRoot`. Since `Math.pow(-4, 1/2)` returns `NaN` and since we only need `Math.abs` for negative numbers, we can use `Math.abs` only for negative **and** odd numbers (not sure the latter is an optimization). So in one line: `let nthRoot = (x, n) => n % 2 === 1 && x < 0 ? -(Math.abs(x) ** (1/n)) : x ** (1/n)` – dotnetCarpenter Mar 20 '20 at 17:37
1

Well, I know this is an old question. But, based on SwiftNinjaPro's answer, I simplified the function and fixed some NaN issues. Note: This function used ES6 feature, arrow function and template strings, and exponentation. So, it might not work in older browsers:

Math.numberRoot = (x, n) => {
  return (((x > 1 || x < -1) && n == 0) ? Infinity : ((x > 0 || x < 0) && n == 0) ? 1 : (x < 0 && n % 2 == 0) ? `${((x < 0 ? -x : x) ** (1 / n))}${"i"}` : (n == 3 && x < 0) ? -Math.cbrt(-x) : (x < 0) ? -((x < 0 ? -x : x) ** (1 / n)) : (n == 3 && x > 0 ? Math.cbrt(x) : (x < 0 ? -x : x) ** (1 / n)));
};

Example:

Math.numberRoot(-64, 3); // Returns -4

Example (Imaginary number result):

Math.numberRoot(-729, 6); // Returns a string containing "3i".
0

Here's a function that tries to return the imaginary number. It also checks for a few common things first, ex: if getting square root of 0 or 1, or getting 0th root of number x

function root(x, n){
        if(x == 1){
          return 1;
        }else if(x == 0 && n > 0){
          return 0;
        }else if(x == 0 && n < 0){
          return Infinity;
        }else if(n == 1){
          return x;
        }else if(n == 0 && x > 1){
          return Infinity;
        }else if(n == 0 && x == 1){
          return 1;
        }else if(n == 0 && x < 1 && x > -1){
          return 0;
        }else if(n == 0){
          return NaN;
        }
        var result = false;
        var num = x;
        var neg = false;
        if(num < 0){
            //not using Math.abs because I need the function to remember if the number was positive or negative
            num = num*-1;
            neg = true;
        }
        if(n == 2){
            //better to use square root if we can
            result = Math.sqrt(num);
        }else if(n == 3){
            //better to use cube root if we can
            result = Math.cbrt(num);
        }else if(n > 3){
            //the method Digital Plane suggested
            result = Math.pow(num, 1/n);
        }else if(n < 0){
            //the method Digital Plane suggested
            result = Math.pow(num, 1/n);
        }
        if(neg && n == 2){
            //if square root, you can just add the imaginary number "i=√-1" to a string answer
            //you should check if the functions return value contains i, before continuing any calculations
            result += 'i';
        }else if(neg && n % 2 !== 0 && n > 0){
            //if the nth root is an odd number, you don't get an imaginary number
            //neg*neg=pos, but neg*neg*neg=neg
            //so you can simply make an odd nth root of a negative number, a negative number
            result = result*-1;
        }else if(neg){
            //if the nth root is an even number that is not 2, things get more complex
            //if someone wants to calculate this further, they can
            //i'm just going to stop at *n√-1 (times the nth root of -1)
            //you should also check if the functions return value contains * or √, before continuing any calculations
            result += '*'+n+√+'-1';
        }
        return result;
    }
SwiftNinjaPro
  • 669
  • 5
  • 15
0

I have written an algorithm but it is slow when you need many numbers after the point:

https://github.com/am-trouzine/Arithmetic-algorithms-in-different-numeral-systems

NRoot(orginal, nthRoot, base, numbersAfterPoint);

The function returns a string.

E.g.

var original = 1000;
var fourthRoot = NRoot(original, 4, 10, 32);
console.log(fourthRoot); 
//5.62341325190349080394951039776481