The natural logarithm can be approximated by the following formula:
$$ln(x) = 2\sum_{k = 0}^{\infty}\frac{(x-1)^{2k+1}}{(2k+1)(x+1)^{2k+1}}$$
I've implemented this formula using Java. Parameter n is the amount of iterations to approximate the natural logarithm.
static double lnApproximation(double x, int n) { double ln = 0; for (int k = 0; k < n; k++) { double a = Math.pow(x - 1, 2*k + 1); double b = 2*k + 1; double c = Math.pow(x + 1, 2*k+1); ln += a/(b*c); } return 2*ln; } I've noticed that my first version has potential to be optimized as calculated factors are not stored temporarily for the next iteration.
/** * Faster than lnApproximation by factor ~5. * Still slower than Math.log that is calling the native system method. */ static double lnApproximationOptimized(double x, int n) { double a = x - 1; double aIteration = Math.pow(x - 1, 2); double b = 1d; double bIteration = 2d; double c = x + 1; double cIteration = Math.pow(x + 1, 2); double ln = a/(b*c); for (int k = 1; k < n; k++) { a *= aIteration; b += bIteration; c *= cIteration; ln += a/(b*c); } return 2*ln; } The optimized version is faster than the first version by the factor ~5. On my machine and the parameters x = 1024, n = 32 the first version takes around 50000 ns to finish. The second version takes around 10000 ns to finish the same thing.
I got curious and wonder if there are more micro optimizations possible here?
Two constraints: First, it has to be Java. Second, it has to be this formula.
System.nanoTime. The first version takes on average 50k ns and the second version takes on average 10k. Of course this is far from professional benchmarking but we can say that the optimized function is faster for sure. \$\endgroup\$std::logfunction and gets, if I calculate correctly, 6ns per logarithm... That makes me assume I do not calculate correctly, but, more importantly, unless I'm off by a factor of ten thousand, it is faster than 10000ns. There's also a random blog article that accuses theFYL2Xassembly instruction of taking up to 700 cycles, which is definitely much less than 10000 nanoseconds. \$\endgroup\$