PDA

View Full Version : log10 function



dampf
- 13th October 2004, 14:55
I have just started writing code in meLabs PicBasic Pro compiler and have so far had great success.

I now need to write a program using 32 bit floating point numbers and a log10 function. I have the floating point part of it working flawlessly. But I have no idea what to do about log10. I downloaded code from Microchip (App Note 660) but I have no idea how to integrate this into my project.

If anyone has done this before, or if they know of another way of doing log10 I would appreciate any help you could give.

If you need any more information please ask me.

Thanks in advance.

mister_e
- 13th October 2004, 15:03
in which formula will you use LOG10 ???

sometime you can refer to simples SCHAUM math series.

let me know

dampf
- 13th October 2004, 15:10
I am not sure I understand your question. This is how I intend on using log10:

result = log10(1/x) - log10(1/y)

x and y are both average values obtained from an analog to digital converter. They are btoh 16 bit integers which I have converted to floating point for this function.

Dwayne
- 13th October 2004, 16:00
Hello Dampf,

D>>If anyone has done this before, or if they know of another way of doing log10 I would appreciate any help you could give.<<


There is a Taylor Series that calculates this. Search in the forum for Tayolr Series, and you should come up with a thread that has calculating Sin via Taylor series.

I will look up the Series for Log base 10... My calculus is a little rusty in remembering these things.

Dwayne

anj
- 13th October 2004, 22:16
Gday Dampf

For logarithms
log(1/n) = - log(n)
log(x/y) = log(x)-log(y)
therefore ( assuming x and y stay integers ) you can rewrite
result = log10(1/x) - log10(1/y) to use integers only

using above relationships you get the following
result = log10(y/x)
and hence
result = log10(y) - log10(x) <-use this instead as easier to calc

I found a nice way to calc logs in base2 which you then convert to baseE / base10 etc as you choose by using a std conversion factor. If you read the "logarithm by calculation" section from
http://www.emesys.com/BS2math3.htm it explains it very well and gives a BS2 code example that you can modify to suit PBP fairly easily.
It has a small footprint and appears to work quite well.
May help you out
Andrew

dampf
- 14th October 2004, 15:39
Hello Anj, and thank you.

I inserted (after slight modification) that routine into my program and it worked great. My only problem is that it only carries it out to 4 places after the decimal point (4.0796 for example). For my application I need a bit more accuracy .. at least a couple more places to the right of the point.

anj
- 14th October 2004, 22:02
Gday Dampf
If that method isnt accurate enough for you, and you have floating point routines, you may want to look at
http://www.dattalo.com/technical/theory/logs.html
Section 5 gives the taylor series method of calculating ln(x), and you can expand this as far as reqd to get the accuracy you require. Not sure if the pic will handle the calcs though )
If it can, then you just use the same method as before to reduce back to log10.
I havent used this method with a PIC, but it may help with what you are trying to do.
Andrew

dampf
- 15th October 2004, 17:54
Thanks everyone for all of your help.

Using the integer LOG10 program from http://www.emesys.com/BS2math3.htm, The ln(x) series from http://www.dattalo.com/technical/theory/logs.html and a bunch of log10/ln/log2 relationships I came up with something that I am happy with.

If anyone wants to use this, feel free. And I am sure some of you smarter folks out there will be able to simplify this greatly. This was fast, dirty, commented poorly, but very rewarding haha.

To use this you must have the floating point routines installed.

y = 16bit integer (I left y=12013 in this program for testing purposes)

there is a loop that goes from 2 to 10. The more times through the loop, the more accurate you get.

Any questions, feel free to ask.

Thanks again for all of your help!!

' LOG10 using LOG2 and LN
y var word ' to hold an input number from 1 to 65535
x var word ' for processing the number
log var word ' to hold the log base 10
j var byte ' loop variable
k var byte ' loop variable
cc var byte ' characteristic
z1 var byte[4] ' to store results
z2 var byte[4] ' to store results

LOG10:
' lg(y) = lg(y/2^cc * (y/(y/2^cc))) = lg(y/2^cc) + lg(y/(y/2^cc))
' = cc + ln(y/2^cc) / ln(2) = cc + ln(y/2^cc) * 1.442695

' starting value y, will be sum from a to d converter
y = 12013 ' log10(y) = 4.07965

cc = ncd y - 1 ' find the characteristic

aint = 1 ' now find 2^cc
Gosub itofa ' a holds the results
bint = 2
Gosub itofb
for i = 1 to cc ' multiply by 2 cc times
gosub fpmul
next i

bint = y
gosub itofb
' now barg equals y
' swap a and b
swap AEXP, BEXP
Swap AARGB0, BARGB0
Swap AARGB1, BARGB1
Swap AARGB2, BARGB2

gosub fpdiv ' a = a/b = y / 2^cc

' now for the fun stuff. We know y / 2^cc < 2 and > 0, so
' calculate ln(a) where -1 < x < 1 using
' ln(1+a) = a - a^2/2 + a^3/3 - a^4/4 + ... - (-a)^n/n
' or ln(a) = (a-1) - (a-1)^2/2 + (a-1)^3/3 - (a-1)^4/4 + ... - (-(a-1))^n/n

bint = 1
gosub itofb
gosub fpsub ' a = a - 1
z2[0] = AEXP
z2[1] = AARGB0
z2[2] = AARGB1
z2[3] = AARGB2
' z2 will hold the results

BEXP = AEXP
BARGB0 = AARGB0
BARGB1 = AARGB1
BARGB2 = AARGB2
aint = 0
gosub itofa
gosub fpsub ' a = - a

z1[0] = AEXP
z1[1] = AARGB0
z1[2] = AARGB1
z1[3] = AARGB2
' z1 = -a
for j = 2 to 10 ' 10 times is accurate enough for us
aint = 1
gosub itofa
BEXP = z1[0]
BARGB0 = z1[1]
BARGB1 = z1[2]
BARGB2 = z1[3]
for k = 1 to j
gosub fpmul ' a = a * b .. a starts as a .. b starts as a
next k
bint = j
gosub itofb
gosub fpdiv ' a should now = (-(a-1))^n/n
BEXP = AEXP
BARGB0 = AARGB0
BARGB1 = AARGB1
BARGB2 = AARGB2 ' now b = a
AEXP = z2[0]
AARGB0 = z2[1]
AARGB1 = z2[2]
AARGB2 = z2[3]
gosub fpsub ' a = results - b
z2[0] = AEXP
z2[1] = AARGB0
z2[2] = AARGB1
z2[3] = AARGB2
next j

' now multiply by 1.442695
AEXP = z2[0]
AARGB0 = z2[1]
AARGB1 = z2[2]
AARGB2 = z2[3]
BEXP = $7F
BARGB0 = $38
BARGB1 = $AA
BARGB2 = $3B
gosub fpmul
bint = cc
gosub itofb
gosub fpadd ' a = a + cc = lg(y)

'log(y) = lg(y) / lg(10) = lg(y) * 0.301029996
BEXP = $7D
BARGB0 = $1A
BARGB1 = $20
BARGB2 = $9B
gosub fpmul

' results in a
Serout2 PORTC.6,16468,[hex AEXP, " ", hex AARGB0, " ", hex AARGB1, " ", hex AARGB2, 13, 10]
pause 500
return