# logarithm and PIC

#### Do you have a question? Post it now! No Registration Necessary

Translate This Thread From English to

•  Subject
• Author
• Posted on
Hi,
I am writing a program for a PIC 16f877.
I must calculate some weather parameters and I have need to calculate the
logarithm in base 10.
Exists some formula/procedure that help me to generate a logarithm of a
number between 10 and 100 with only 4 decimal digit?
I know that the result is a real but then I will put it in more byte and
display it.
thanks for the info
stefano

Re: logarithm and PIC

I'm not sure if I understand exactly what you're looking for, so I'll
repeat the question back to you and you can correct it if I have
misunderstood.  What you want is an approximation of a log10 function
with a maximum error of less than 1e-4 over the range (10,100).  If
that's correct, then there are a couple of ways to do that.  One way
would be to use an series approximation.  One that will (mathematically)

log10(x) = 0.215228608 + .1362859914*x - 0.8941598030e-2*x^2 +
0.4317913455e-3*x^3 - 0.1439966989e-4*x^4 + 0.3302136507e-6*x^5

This has a maximum error of 0.7626633405e-4 in the range (10,100) but as
you can see, it's a little complex (and probably quite slow) for a PIC
to calculate.  FYI, I generated this approximation in just a couple of
seconds using Maple.  (see http://www.maplesoft.com )  Specifically, I
used the minimax function, but there are other means of turning
trancendental functions into series approximations, e.g Chebyshev, (see
http://mathworld.wolfram.com/ChebyshevApproximationFormula.html ) and
http://mathworld.wolfram.com/ChebyshevApproximationFormula.html and
links).  If you find calculus scary, don't look!  :-)

The more usual method is to use a table lookup.  Since you need so much
precision, you'll have to use a table and interpolation.  Conceptually,
this is done by approximating the curve as  a series of straight lines,
and there are a couple of ways to "slice" the curve.  One way is to
divide up the curve at equally spaced intervals, and another way is to
divide up the curve so that the straight line approximation between the
two points is less than or equal to your desired error term.  You might
do it the first way to save on lookup time at the expense of ROM table
size or the second way to economize a little on ROM at the expense of
lookup time.  (In some circumstances that require less precision than
yours, you can use just a simple lookup.)

You can create the tables yourself with a simple program on your desktop
machine.  How you do it depends on a lot of things, not least of which
is the number representation you decide to use in the PIC.  Obvious
options include fixed point and floating point, but floating point on a
PIC is going to be painful if you haven't done this kind of thing before.

If this explanation doesn't help, try asking again with a little more
detail.

Ed

Re: logarithm and PIC

--- clip clip ---

In a binary computer, the logarithm is often easier to
calculate in base 2, so only the interval (1,2) needs
to be considered. The number is normalized into the
interval by plain bit shifts, and the shift count
remembered. The shift count is the integer part of
base 2 logarithm to be added to the tabulated/interpolated
result.

In any case, logarithm is the most complicated elementary
function to calculate from a series.

Which format are your input data in?

For integers, by far the easiest way is a table
with all the entries in the range you're interested,
even though a constant table is a kind of PITA
in a PIC.

--

Tauno Voipio
tauno voipio (at) iki fi

Re: logarithm and PIC

my data is integer with range from 10..100

you have reason, only now i have understood that calculate the logarithms
with series it is much complicated , I will have to reserve 90 cells of
memory in order to insert the logarithms table

thanks
stefano

Re: logarithm and PIC

That makes things simpler.

You might save space if you store just the values of 10, 20, etc and
then linearly interpolate for the values in between.

Kelly

Re: logarithm and PIC
->
-> In any case, logarithm is the most complicated elementary
-> function to calculate from a series.
->
-> Which format are your input data in?
->
-> For integers, by far the easiest way is a table
-> with all the entries in the range you're interested,
-> even though a constant table is a kind of PITA
-> in a PIC.
->
-
-my data is integer with range from 10..100
-
-you have reason, only now i have understood that calculate the logarithms
-with series it is much complicated , I will have to reserve 90 cells of
-memory in order to insert the logarithms table

A very small price to pay as compared to having to try to actually compute it

BTW I don't think 8 bits gives you the precision you require. You'll need
a miniumum of 14 bits to get down to 1/10000 resolution.

BAJ

Re: logarithm and PIC

......
......

it is corrected you have understood my bad english.!!
I have tried to insert the series in excel but it does not work correctly

thanks
stefano

Re: logarithm and PIC

You're absolutely right.  Apparently a cut-and-paste error.  My
apologies! Here's a correct form:

f(x) :=
.2152286561+(.1362859746+(-0.8941595723e-2+(0.4317911768e-3+(-0.1439966252e-4+(0.3302134471e-6+(-0.5177507477e-8+(0.5440287309e-10+(-0.3656629823e-12+(0.1419115613e-14-0.2416529628e-17*x)*x)*x)*x)*x)*x)*x)*x)*x)*x

It's also in a form that's a bit easier for a computer to use.

However, I see that in another message you say that your inputs are
integers.  If that's the case and the range is only 10-100, you are
definitely better off using a table!  Here's a table version in C
showing the values and also the approximate error terms which should all
be less than 1e-4.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

short int log10table[] = {
0x0000,0x0A98,0x1445,0x1D2B,0x2568,0x2D14,0x3441,0x3AFE,
0x4159,0x475C,0x4D10,0x527C,0x57A9,0x5C9A,0x6155,0x65DF,
0x6A3B,0x6E6D,0x7278,0x765F,0x7A24,0x7DC9,0x8151,0x84BD,
0x880F,0x8B48,0x8E69,0x9175,0x946C,0x9750,0x9A20,0x9CDF,
0x9F8D,0xA22A,0xA4B9,0xA738,0xA9AA,0xAC0E,0xAE65,0xB0B0,
0xB2EF,0xB523,0xB74B,0xB96A,0xBB7E,0xBD88,0xBF89,0xC181,
0xD1CD,0xD379,0xD51F,0xD6BE,0xD858,0xD9EC,0xDB7A,0xDD02,
0xDE85,0xE004,0xE17C,0xE2F1,0xE460,0xE5CA,0xE730,0xE892,
0xE9EF,0xEB48,0xEC9D,0xEDEE,0xEF3B,0xF084,0xF1C9,0xF30B,
0xF449,0xF583,0xF6BA,0xF7EE,0xF91E,0xFA4C,0xFB76,0xFC9D,
0xFDC0,0xFEE1,0xFFFF
};

int main()
{
int i;
double x;

for (i10%; i < 101; i++)
{
x = 1.0 + (log10table[i-10]/65536.0);
if (i > 31) x = x + 1.0;
printf("%d\t%f\t%g\n", i, x, log10(i)-x);
}
return 0;
}

There are ways to optimize this, of course, but this should get you
started with something that works.  Also, in the real code, don't forget
about range checking!  You don't want to go off the end of the table.

Ed

Re: logarithm and PIC

Wow Ed, that was great of you to do that!

Re: logarithm and PIC
| One way
| would be to use an series approximation.  One that will (mathematically)
|
| log10(x) = 0.215228608 + .1362859914*x - 0.8941598030e-2*x^2 +
| 0.4317913455e-3*x^3 - 0.1439966989e-4*x^4 + 0.3302136507e-6*x^5

This equation can be reduced to 0.215228608 + x*(0.1362859914 -
x*(0.894159803e-2 - x*(0.4317913455e-3 - x*(0.1439966989e-4 -
x*(0.3302136507e-6)))))

This reduces the number of multiplications from 9 to 5.

--
MT

Re: logarithm and PIC

Jack Crenshaw had an article on a clever way of calculating a base-2
logarithm in the March 1998 issue of Embedded Systems Programming. Also
in his "Math Toolkit for Real-Time Programming" (ISBN 1-929629-09-5).
There are a few descriptions on-line; google for "Crenshaw bitlog".

--
Rich Webb   Norfolk, VA

Re: logarithm and PIC

Keep in mind that a straight lookup table has almost no code, plus if
you intend to display the result you can put the final display values
in the table.  If you implement a log10 algorithm it has to be smaller
than a 90 element table (you did later say the input was integer, right?)
if you want to save space.

--
Ben Jackson
We've slightly trimmed the long signature. Click to see the full one.