PDA

View Full Version : Log?



Joe123
12-13-2008, 06:58 AM
Why can't we have Log =(

Gleeok
12-13-2008, 08:26 AM
LOG!! (http://www.youtube.com/watch?v=dPHtKarae2Q)-by blammo




PS: ...What?!

Joe123
12-13-2008, 08:32 AM
Logarithms.

'What power of X (usually e or 10, I need base 10) is this number'

Elmensajero
12-14-2008, 05:40 PM
Well, I attempted to script this, but it didn't work out so well. I wrote ln(x) which works for any positive value x (even decimals), but after testing it with multiple inputs it had an average of 2% error. Most were below 1% error, but there were quite a few values that triggerered really high errors, for example inputting x=.8192 gave a 20% error (the highest I saw during testing.) Most of these errors I believe are due to only having 4 decimal places available, but it could also have to do with the algorithm I wrote. After using change-of-base to convert into log(base,exp) and log10(x), the average percent error shot up to 41% and 57% respectively, and I don't really feel like messing with this anymore. So, if anyone wants to use any of the code I wrote to attampt to implement this better while waiting for one of the devs to add it, go right ahead. They aren't fully commented, but if you look at this page about computing ln(x) (http://en.wikipedia.org/wiki/Natural_logarithm#High_precision) and this page on Arithmetic-geometric mean (http://en.wikipedia.org/wiki/Arithmetic-geometric_mean), you should be able to figure out the algorithm I used. I didn't even try to use a Taylor series approximation, so I am not sure if that would work better or not.

By the way, Joe123, what are you trying to script that involves logarithms?



import "std.zh"

bool ERROR_LN=false;

//arithmetic-geometric mean
int Agm(int x,int y)
{
int a;
int g;
int temp_a;
int temp_g;
int counter=0;

a=(x+y)/2;
g=Sqrt(x*y);
while(a!=g && counter<1000)
{
temp_a=(a+g)/2;
temp_g=Sqrt(a*g);
a=temp_a;
g=temp_g;
counter++; //prevents infinite loop that prob wouldn't happen anyways
}
return a;
}

//natural log of x, returns "1000" if an error occurs
float Ln(float x)
{
float m=2;
float s=x*Pow(2,m);
float prev_m=m;
float temp;
int p=6; //digits of precision

if(x<=0)
{
ERROR_LN=true;
return 1000; //ln(0) and log of negative number undefined
}
if(x==1) return 0;

//calculate number to maintain "p" digits of precision
while(s<=Pow(2,Ceiling(p/2)))
{
m*=2;
if(m<0 || prev_m>m) //I doubt this could happen, but prevents infinte loop
{
ERROR_LN=true;
return 1000;
}
prev_m=m;
s=x*Pow(2,m);
}

//calculate ln(x) based on Newton's method to invert the exponential function
temp=2*Agm(1,4/s);
if(temp==0) //prevents divide-by-zero error
{
ERROR_LN=true;
return 1000;
}
return PI/temp-m*0.6931; //ln(2) roughly equals 0.6931
}

//standard logarithm of x with specific base, no error checking at the moment
float Log(float base,float x)
{
return (Ln(x)/Ln(base));
}

//common log of x, no error checking at the moment
float Log10(float x)
{
return Log(10,x);
}

Joe123
12-14-2008, 05:56 PM
I wanted to work out how many digits there were in a number for a script which displays prices on items in a shop.

I was going to use Floor(log10(x)) anyway, so I precision isn't paramount =P

I'll have a go with this but I think it might be a bit over the top, I'm just using ifs to check it instead at the moment.

I assumed it wouldn't be that much effort for the developers to add another mathematical function into ZScript; they're not hard to access in C++ and we have quite a few already, so it'd probably just be copying over some code, right?


Just Joe is fine by the way =P

beefster09
12-18-2008, 09:46 PM
If that's the case, then check if it is larger than or smaller than 999999 or whatever number. Sure it's tedious, but it works better anyway. It's what I did in my shop script.

Joe123
12-19-2008, 04:24 AM
Yeah, that's what I've done.
It's not better, but seeing as we don't have logs it does work =P

plith
01-04-2009, 10:47 PM
Incidentally, I took a stab at a Taylor series expansion. It works fine for small numbers (centered around 1), but it breaks down pretty quickly as you move away from 1. Not worth the time and effort.