static public BigDecimal root ( final int n , final BigDecimal x ) { if ( x . compareTo ( BigDecimal . ZERO ) < 0 ) { throw new ArithmeticException ( "negative argument " + x . toString ( ) + " of root" ) ; } if ( n <= 0 ) { throw new ArithmeticException ( "negative power " + n + " of root" ) ; } if ( n == 1 ) { return x ; } /* start the computation from a double precision estimate */ BigDecimal s = new BigDecimal ( Math . pow ( x . doubleValue ( ) , 1.0 / n ) ) ; /* this creates nth with nominal precision of 1 digit */ final BigDecimal nth = new BigDecimal ( n ) ; /* Specify an internal accuracy within the loop which is * slightly larger than what is demanded by ’eps’ below. */ final BigDecimal xhighpr = scalePrec ( x , 2 ) ; MathContext mc = new MathContext ( 2 + x . precision ( ) ) ; /* Relative accuracy of the result is eps. */ final double eps = x . ulp ( ) . doubleValue ( ) / ( 2 * n * x . doubleValue ( ) ) ; for ( ; ; ) { /* s = s -(s/n-x/n/s^(n-1)) = s-(s-x/s^(n-1))/n; test correction s/n-x/s for being * smaller than the precision requested. The relative correction is (1-x/s^n)/n, */ BigDecimal c = xhighpr . divide ( s . pow ( n - 1 ) , mc ) ; c = s . subtract ( c ) ; MathContext locmc = new MathContext ( c . precision ( ) ) ; c = c . divide ( nth , locmc ) ; s = s . subtract ( c ) ; if ( Math . abs ( c . doubleValue ( ) / s . doubleValue ( ) ) < eps ) { break ; } } return s . round ( new MathContext ( err2prec ( eps ) ) ) ; }
The integer root .