2

How do I extract the nth root of a BigInt in JavaScript?

Math.pow doesn't work.

Jesus is Lord
  • 14,971
  • 11
  • 66
  • 97

1 Answers1

3

Converted to JavaScript's BigInt notation, based off of Nth root of BigInteger from Java as suggested by Dai in the comments. Make sure that base and root that are passed in are BigInt's, if not then you can just set base = BigInt(base); etc. for the two inputs. This is based off of Newton's formula. Also, BigInt's can't represent decimals, so every division is floored division so this doesn't work for the cube root of 16, for example. Here's some Mozilla documentation of BigInt that is worth the read: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt

function iroot(base, root) {
  if (typeof base !== 'bigint' || typeof root !== 'bigint') throw new Error("Arguments must be bigints.");

  let s = base + 1n;
  let k1 = root - 1n;
  let u = base;
  while (u < s) {
    s = u;
    u = ((u*k1) + base / (u ** k1)) / root;
  }
  return s;
}
Dai
  • 141,631
  • 28
  • 261
  • 374
Samathingamajig
  • 11,839
  • 3
  • 12
  • 34
  • 1
    Huh... [TIL that `**` is a valid operator in JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Exponentiation)! - and it **is** defined for `number` **and** `BigInt`. – Dai Oct 04 '20 at 01:39
  • 1
    ** is the Exponentiation operator... – Sxribe Oct 04 '20 at 01:40
  • Yup! It works in Python too and I also think Java but I'm not sure. I was a little confused when I was translating this to JavaScript because of the weird naming conventions of the pseudo code, but I was able to figure out that in the original pseudo code, the first number was actually the root and the second number was the base, so I switched it around in this solution to make more sense, like how Math.pow() works. – Samathingamajig Oct 04 '20 at 01:42
  • @Sxribe, most people are taught and most people use `Math.pow(base, exponent)` in JavaScript, I don't know why but I think they are taught in classes to use that since they don't forget to put the second asterisk and get confused. – Samathingamajig Oct 04 '20 at 01:46
  • 1
    BTW, it might be an idea to add a type-check to `base` and `root` and throwing an exception if the types aren't actual `bigint` values because I think this function may still run (but not produce a useful result) if non-bigint values are provided. I've edited the answer to add that check. This also means the function will fail when used in a JS environment without BigInt, like Internet Explorer or `wscript`/`cscript`. – Dai Oct 04 '20 at 02:05
  • 1
    @Samathingamajig Man, that is incredibly stupid IMO. `**` is WAY more concise. Concise code is better code. – Sxribe Oct 04 '20 at 02:16
  • @Dai, the function already returned errors due to how BigInts work in JS, but it's a good idea to add that double-checking for when it's used in non-modern versions. – Samathingamajig Oct 04 '20 at 02:35
  • @Sxribe I agree that Math.pow() is way less concise. I just looked it up, and according to [this article](https://mariusschulz.com/blog/the-exponentiation-operator-in-javascript), the `**` exponentiation operator was added in ES6, and when compiled down to previous versions it's converted to `Math.pow()`, but yeah schools and youtubers should be teaching the `**` since that's more modern, and you can always just run a compiler to convert it down a few versions. – Samathingamajig Oct 04 '20 at 02:40
  • @Samathingamajig Only ES6? Damn thats weird – Sxribe Oct 04 '20 at 03:48