logarithm and PIC

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

Reply to
xxx
Loading thread data ...

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) meet your requirements is

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

formatting link
) Specifically, I used the minimax function, but there are other means of turning trancendental functions into series approximations, e.g Chebyshev, (see
formatting link
) and and Pade-Chebyshev. (see
formatting link
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

Reply to
Ed Beroset

--- 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
Reply to
Tauno Voipio

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
Reply to
Rich Webb

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

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

Reply to
xxx

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

Reply to
xxx

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

Reply to
Kelly Hall

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

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, 0xC370,0xC556,0xC734,0xC90B,0xCADA,0xCCA1,0xCE61,0xD01B, 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 (i=10; 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

Reply to
Ed Beroset

The artist formerly known as Ed Beroset wrote: | One way | would be to use an series approximation. One that will (mathematically) | meet your requirements is | | 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

To reply directly, please first take your dick out of my address.
Reply to
mark thomas

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

http://www.ben.com/
Reply to
Ben Jackson

->

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

Reply to
Byron A Jeff

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

Reply to
John Harlow

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.