MikeMcl / decimal.js

An arbitrary-precision Decimal type for JavaScript
http://mikemcl.github.io/decimal.js
MIT License
6.45k stars 475 forks source link

Support for nth root #156

Open isaac-holt opened 4 years ago

isaac-holt commented 4 years ago

It would be good to have a nthRoot method to calculate any integer root of a number exactly, as for a root like 6, pow(1/6) leads to a slight loss of precision.

MikeMcl commented 4 years ago

Yes, I will consider it. Related.

joaomilho commented 3 years ago

How's this consideration going? :D

This would be handy.

MikeMcl commented 3 years ago

@joaomilho

The nth root can be found using pow, for example:

Decimal.prototype.nthRoot = function (n) {
  return this.pow(new Decimal(1).div(n));
}

Or more properly:

Decimal.prototype.nthRoot = function (n, guardDigits = 6) {
  const x = this;
  const D = x.constructor;
  const one = new D(1);
  n = new D(n);
  if (n.lt(one) || !n.isInteger()) {
    throw Error('n must be a positive integer');
  };
  if (x.isZero()) return new D(x);
  const p = D.precision;
  const r = D.rounding;
  D.precision = p + guardDigits;
  D.rounding = D.ROUND_DOWN;
  const y = one.div(n);
  D.precision = p;
  D.rounding = r;
  return x.pow(y);
};

const x  = new Decimal(27);
console.log( x.nthRoot(3).toString() );    // '3'

Using Newton's method would be faster, in the same way as using sqrt in this library is faster than using pow(0.5), but I do not have time at the moment to write and test a proper implementation.

Note that the above implementations are for demonstration purposes and have not been tested.