Is it possible to calculate $\log_{10} x$ without using $\log_{10}$? I'm interested because I'm working with a framework that has some simple functions, but log is not one of them.
The specific platform is capable of doing addition, subtraction, multiplication and division. I can write a formula of a finite, predefined length; e.g. while loops or for loops that continue indefinitely are not available. It's a black-box project with an interface capable of creating formulas, so basically, I need to write the expression to calculate $\log_{10} x$ in one line, and I can't write my own method or something to do more dynamic calculations.
An approximation of $\log_{10} x$ is perfectly acceptable.
$\endgroup$ 67 Answers
$\begingroup$Write $x=a\times 10^b$ with $0<a<1$. So, $$\log_{10}x=b+\log_{10}(a)=b+\frac{\log (a)}{\log (10)}$$ Now, use the very fast convergent series expansion $$\log\Big(\frac{1+x}{1-x}\Big)=2\Big(\frac{x}{1}+\frac{x^3}{3}++\frac{x^5}{5}+\cdots\Big)$$ using $a=\frac{1+x}{1-x}$ that is to say $x=\frac{a-1}{a+1}$ and you know that $\log(10)\approx 2.30259$.
$\endgroup$ 5 $\begingroup$The CORDIC algorithms may help here (used by most calculators working in BCD in the old days because requiring only additions and shifts).
It uses an array $\rm{L}$ of precalculated logarithms in base $10$ ($\log$ means $\log_{10}$ here) and
$x$ will be supposed written using digits (with a decimal point) :
L= [log(2), log(1.1), log(1.01), ... , log(1.000001)];The relation $\;\displaystyle \log(x) = \log\left(x\,10^{−n}\right) + n\;\;$ is used to get all positive real values $x$ in the range $(1,10]\;$ ($n$ is the number of shifts of the decimal points required for this purpose, $10^{−n}$ really means "right-shift of $n$" for $n>0$).
The algorithm may then be applied to $\;x\mapsto x\,10^{−n}$ :
k= 0; y= 0; p= 1; //p is the partial product
while (k <= 6)
{ while (x >= p+p*10^(-k)) { y= y+L[k]; // L[k] = log(1+10^{-k}) p= p+p*10^(-k); } k= k+1;
}
return y;The idea is that for $$x=(1+1)^{n_0}\,(1+10^{-1})^{n_1}\,(1+10^{-2})^{n_2}\cdots (1+10^{-6})^{n_6}(1+\epsilon)$$ we will get $$\log(x)=n_0\log(1+1)+n_1\log(1+10^{-1})+\cdots+n_6\log(1+10^{-6})$$ and the precision should be near $7$ digits with the upperbound $6$ (more terms means more precision).
$\endgroup$ 1 $\begingroup$You can use a Taylor polynomial to first roughly compute $\ln n$. $$\ln n\approx0+\dfrac{1}{1!}(n-1)+\dfrac{(\frac{-1}{n^2})}{2!}(n-1)^2+\dfrac{(\frac{2}{n^3})}{3!}(n-1)^3+\dfrac{(\frac{-6}{n^4})}{4!}(n-1)^4+\dfrac{(\frac{24}{n^5})}{5!}(n-1)^5$$ Then use the fact that $\ln 10 \approx2.302585092994046$, so divide $\ln n$ by that to get $\log_{10} n$
$\endgroup$ 8 $\begingroup$Many platforms will at least have a function for the natural logarithm ($\ln$).
Note that $\log_{10}(x) = \ln(x)/\ln(10)$.
$\endgroup$ 1 $\begingroup$There also exists an approximation of the logarithm from the arithmetric-geometric mean:
$$\ln x\approx\frac{\pi}{2M_{AG}(1,\frac{4}{s})}-m\ln(2)$$ where $s=2^m.x>2^\frac{p}{2}$ and error is about $\frac{\ln x}{2^p}$
This is interesting because this mean converges quickly, so you can get a better approximation than with by using Taylor series at least for general numbers. All you need to have is a definition of constants $\pi$ and $ln(2)$ with good precision.
You do not need to know $p$ in practice, this is just to show the order of precision obtained. $2^m$ is also easy to compute because it is a simple integer shift, the bigger the $m$ you choose, the bigger precision you get. I tested with $m=31$ just to stay within 32 bits types, and I got more than 10 exact decimals for $\ln x$.
And $M_{AG}$ can be calculated easily in a simple for loop, in general for usual floats double precision, it converges in less than 10 steps.
To get $\log_{10}(x)$ just divide the result by another constant $\ln(10)$.
$\endgroup$ $\begingroup$You can use the formula posted above by Mastrem, but it works good enough only when n is close to 1. When n is not close to 1, then that formula gives a result with big error, and when n is a big number that formula is not applicable at all.
What to do? When n is a big number you can use the property of log, which states that $$log_a(b)^c = c \; log_a (b) $$
If you have to find ln n, and n is a big number, then you must first take 10 times (just 10 is enough for any big number) the square root of n. Let us name this new number $\alpha$:
$$\alpha = \sqrt(\sqrt(\sqrt(\sqrt(\sqrt(\sqrt(\sqrt(\sqrt(\sqrt(\sqrt(n))))))))))$$ (using the standard denomination for square root function in many programs)
so,
$$n = ((((((((((\alpha)^2)^2)^2)^2)^2)^2)^2)^2)^2)^2$$
and we can write: $$ln \,n = ln((((((((((\alpha)^2)^2)^2)^2)^2)^2)^2)^2)^2)^2$$
an using the log property explained above: $$ln \,n = 2\cdot2\cdot2\cdot2\cdot2\cdot2\cdot2\cdot2\, ln (\alpha) = 1024\, ln \,(\alpha) $$
where $\alpha$ will be always very close to 1, and the formula of Mastrem above can be used.
$\endgroup$ 1 $\begingroup$Let x = 1545 and proceed as follows:
Divide x by base 10 until x becomes smaller than base 10. 1545/10 = 154.5 154.5 / 10 = 15.45 15.45 / 10 = 1.545 As we divide 3 times the value of x by 10, the whole digit of our logarithm will be 3.
Raise x to the tenth power: 1.545 ^ 10 = 77.4969905 ...
Repeat the procedures from step 1.
As we divide only 1 time, the next digit of our logarithm will be 1.
- Repeat step 2.
7.74969905 ... ^ 10 = 781.354.964,875286221 ...
- Repeat step 1.
Since we divide x by 10 by 8 times, the next digit in our log will be 8.
And so on, as many digits as you want.
$\endgroup$