# Implementation of natural logarithm without using power functions ###### tags: `archived` `note` `math` So, we know that with a function $ln(x)$ we could calculate it to the $n^{th}$ precision with this function $$ ln(x) = 2 \sum^\infty_{i=1}[\frac{1}{2i-1}(\frac{x-1}{x+1})^{2i-1}] $$ At least the textbook said so and I'm lazy to verify. Of course, you could just use a Taylor series to figure out the answer but that's not the point. The purpose of this is to figure out the $n^{th}$ percision of a $ln(x)$ function. ## Background This is just to help out with my friends homework. If there's any questions about this post please email me at b0670504@ntu.edu.tw. Would try to respond as soon as possible. ## Math section So for explanation purposes we could split up the equation - Coefficient $\frac{1}{2i-1}$ - Alpha part $(\frac{x-1}{x+1})^{2i-1}$ Now, in the textbook it writes: > ...it might be useful to expand series for a few terms to see how the $\alpha$ component of a term can be derived from the $\alpha$ component of its predecessor... So let's do excatly that! So when `i >= 1`, the function would look like this: $$ ln(x) = 2 \times \frac{1}{1}(\frac{x-1}{x+1})^{1} $$ Okay, so what happens when `i >= 2`? $$ ln(x) = 2 \times (\frac{1}{1}(\frac{x-1}{x+1})^{1} + \frac{1}{3}(\frac{x-1}{x+1})^{3}) $$ And then, `i >= 3`? $$ ln(x) = 2 \times (\frac{1}{1}(\frac{x-1}{x+1})^{1} + \frac{1}{3}(\frac{x-1}{x+1})^{3} + \frac{1}{5}(\frac{x-1}{x+1})^{5}) $$ You get the idea. So what kind of pattern do we see? $$ (\frac{x-1}{x+1})^{3} = (\frac{x-1}{x+1})^{1} \times \frac{x-1}{x+1} \times \frac{x-1}{x+1} $$ And $$ (\frac{x-1}{x+1})^{5} = (\frac{x-1}{x+1})^{3} \times \frac{x-1}{x+1} \times \frac{x-1}{x+1} $$ So we could see a pattern that: $$ (\frac{x-1}{x+1})^{n} = (\frac{x-1}{x+1})^{n-2} \times \frac{x-1}{x+1} \times \frac{x-1}{x+1} $$ Therefore, if you say, save the answer for the `power of 1`, then you could just multiply it by 2 $\alpha$ and get the answer of `power of 3`. Similarly, you could get the answer for the `power of 5` by multiplying the answer of `power of 3` by 2 $\alpha$ again. **The key to this problem would be to just save the previous answer and multiply it by 2 $\alpha$ and you will get the next answer!** ## Code implementation So in the naive function, written in `C`: ```c= float naiveln(float x, float n) { float ans = 0, alpha = (x-1)/(x+1); for (int i = 1 ; i <= n ; i++) { ans += (1.0/(2*i-1))*(pow(alpha, (2*i-1))); } return 2.0*ans; } ``` and say the `pow` function is an expensive function to use (somewhat) and we want to get rid of it. So, let's use multiplications instead: ```c= float smartln(float x, float n) { float alpha = (x-1)/(x+1), ans = alpha; float save = ans * alpha * alpha; for (int i = 2 ; i <= n ; i++) { ans += (1.0/(2*i-1)) * save; save = save * alpha * alpha; } return 2.0*ans; } ``` The full `C` code: ```c= /* Compiler= gcc C standard>= c99 Compile= gcc ln.c -o ln -lm Execute= ./ln */ #include <stdlib.h> #include <stdio.h> #include <math.h> float smartln(float x, float n) { float alpha = (x-1)/(x+1), ans = alpha; float save = ans * alpha * alpha; for (int i = 2 ; i <= n ; i++) { ans += (1.0/(2*i-1)) * save; save = save * alpha * alpha; } return 2.0*ans; } float naiveln(float x, float n) { float ans = 0, alpha = (x-1)/(x+1); for (int i = 1 ; i <= n ; i++) { ans += (1.0/(2*i-1))*(pow(alpha, (2*i-1))); } return 2.0*ans; } int main() { float x, n; printf("X value:"); scanf("%f", &x); printf("N value:"); scanf("%f", &n); // Checking the values if (x <= 0 || n <= 0) { puts("Invalid arguments"); return -1; } printf("Naive ln(x) = %f\n", naiveln(x, n)); printf("Smart ln(x) = %f\n", smartln(x, n)); return 0; } ``` The makefile ```bash= all: ln.o gcc -g ln.o -o ln -lm ln.o: ln.c gcc -g -c ln.c clean: rm ln ln.o ```