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?
29 Answers
Can you use something like this?
Math.pow(n, 1/root); eg.
Math.pow(25, 1/2) == 5 5The 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) 1Use Math.pow()
Note that it does not handle negative nicely - here is a discussion and some code that does
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){} } 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(); 0The 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
xis positive andris even. - There is one positive solution when
xis positive andris odd. - There is one negative solution when
xis negative andris odd. - There is no solution when
xis negative andris 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) 2For 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 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". 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; } 2I have written an algorithm but it is slow when you need many numbers after the point:
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