java - Logarithm of a BigDecimal -


how can calculate logarithm of bigdecimal? know of algorithms can use?

my googling far has come (useless) idea of converting double , using math.log.

i provide precision of answer required.

edit: base do. if it's easier in base x, i'll that.

java number cruncher: java programmer's guide numerical computing provides solution using newton's method. source code book available here. following has been taken chapter 12.5 big decmial functions (p330 & p331):

/**  * compute natural logarithm of x given scale, x > 0.  */ public static bigdecimal ln(bigdecimal x, int scale) {     // check x > 0.     if (x.signum() <= 0) {         throw new illegalargumentexception("x <= 0");     }      // number of digits left of decimal point.     int magnitude = x.tostring().length() - x.scale() - 1;      if (magnitude < 3) {         return lnnewton(x, scale);     }      // compute magnitude*ln(x^(1/magnitude)).     else {          // x^(1/magnitude)         bigdecimal root = introot(x, magnitude, scale);          // ln(x^(1/magnitude))         bigdecimal lnroot = lnnewton(root, scale);          // magnitude*ln(x^(1/magnitude))         return bigdecimal.valueof(magnitude).multiply(lnroot)                     .setscale(scale, bigdecimal.round_half_even);     } }  /**  * compute natural logarithm of x given scale, x > 0.  * use newton's algorithm.  */ private static bigdecimal lnnewton(bigdecimal x, int scale) {     int        sp1 = scale + 1;     bigdecimal n   = x;     bigdecimal term;      // convergence tolerance = 5*(10^-(scale+1))     bigdecimal tolerance = bigdecimal.valueof(5)                                         .movepointleft(sp1);      // loop until approximations converge     // (two successive approximations within tolerance).     {          // e^x         bigdecimal etox = exp(x, sp1);          // (e^x - n)/e^x         term = etox.subtract(n)                     .divide(etox, sp1, bigdecimal.round_down);          // x - (e^x - n)/e^x         x = x.subtract(term);          thread.yield();     } while (term.compareto(tolerance) > 0);      return x.setscale(scale, bigdecimal.round_half_even); }  /**  * compute integral root of x given scale, x >= 0.  * use newton's algorithm.  * @param x value of x  * @param index integral root value  * @param scale desired scale of result  * @return result value  */ public static bigdecimal introot(bigdecimal x, long index,                                  int scale) {     // check x >= 0.     if (x.signum() < 0) {         throw new illegalargumentexception("x < 0");     }      int        sp1 = scale + 1;     bigdecimal n   = x;     bigdecimal   = bigdecimal.valueof(index);     bigdecimal im1 = bigdecimal.valueof(index-1);     bigdecimal tolerance = bigdecimal.valueof(5)                                         .movepointleft(sp1);     bigdecimal xprev;      // initial approximation x/index.     x = x.divide(i, scale, bigdecimal.round_half_even);      // loop until approximations converge     // (two successive approximations equal after rounding).     {         // x^(index-1)         bigdecimal xtoim1 = intpower(x, index-1, sp1);          // x^index         bigdecimal xtoi =                 x.multiply(xtoim1)                     .setscale(sp1, bigdecimal.round_half_even);          // n + (index-1)*(x^index)         bigdecimal numerator =                 n.add(im1.multiply(xtoi))                     .setscale(sp1, bigdecimal.round_half_even);          // (index*(x^(index-1))         bigdecimal denominator =                 i.multiply(xtoim1)                     .setscale(sp1, bigdecimal.round_half_even);          // x = (n + (index-1)*(x^index)) / (index*(x^(index-1)))         xprev = x;         x = numerator                 .divide(denominator, sp1, bigdecimal.round_down);          thread.yield();     } while (x.subtract(xprev).abs().compareto(tolerance) > 0);      return x; }  /**  * compute e^x given scale.  * break x whole , fraction parts ,  * compute (e^(1 + fraction/whole))^whole using taylor's formula.  * @param x value of x  * @param scale desired scale of result  * @return result value  */ public static bigdecimal exp(bigdecimal x, int scale) {     // e^0 = 1     if (x.signum() == 0) {         return bigdecimal.valueof(1);     }      // if x negative, return 1/(e^-x).     else if (x.signum() == -1) {         return bigdecimal.valueof(1)                     .divide(exp(x.negate(), scale), scale,                             bigdecimal.round_half_even);     }      // compute whole part of x.     bigdecimal xwhole = x.setscale(0, bigdecimal.round_down);      // if there isn't whole part, compute , return e^x.     if (xwhole.signum() == 0) return exptaylor(x, scale);      // compute fraction part of x.     bigdecimal xfraction = x.subtract(xwhole);      // z = 1 + fraction/whole     bigdecimal z = bigdecimal.valueof(1)                         .add(xfraction.divide(                                 xwhole, scale,                                 bigdecimal.round_half_even));      // t = e^z     bigdecimal t = exptaylor(z, scale);      bigdecimal maxlong = bigdecimal.valueof(long.max_value);     bigdecimal result  = bigdecimal.valueof(1);      // compute , return t^whole using intpower().     // if whole > long.max_value, first compute products     // of e^long.max_value.     while (xwhole.compareto(maxlong) >= 0) {         result = result.multiply(                             intpower(t, long.max_value, scale))                     .setscale(scale, bigdecimal.round_half_even);         xwhole = xwhole.subtract(maxlong);          thread.yield();     }     return result.multiply(intpower(t, xwhole.longvalue(), scale))                     .setscale(scale, bigdecimal.round_half_even); } 

Comments

Popular posts from this blog

amazon web services - S3 Pre-signed POST validate file type? -

c# - Check Keyboard Input Winforms -