# 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
```