Sire


Hi all,

Perhaps someone can help me with this. I just got the payback for skipping too many math classes, so bear with me and my misuse of math terms...

I want a function that converts a linear value to a logarithmic counterpart, with the ability to adjust the "curve" of the logarithmic scale.

The function can look something like this:

Code Snippet

double Scale(double value, double base, double maxValue)


value = what I want to convert to it's logarithmic counterpart
base = describes the logarithmic curve. For example 1 = linear, and -1 and +1 are the extremes in either direction
maxValue = this value should count as the extreme end of the curve

See this image for an idea of what I'm looking for:
http://en.wikipedia.org/wiki/Image:600px-LinLinScale.png

The results are not going to be used scientifically so it doesn't matter that "a logarithmic scale cannot have a maxvalue" etc. The results are just going to help humans making decisions, so they don't have to be (actually they can't be) exact.

Example output:

Code Snippet

value base maxvalue returns
1 0.7 20 0.01
2 0.7 20 0.03
3 0.7 20 0.10
4 0.7 20 0.20
20 0.7 20 1
30 0.7 20 1

With a higher base, the increase of the returnvalue would be more dramatic.

This could be solved with a simple Math.Pow(value, baseValue), but that curve isn't flexible enough. I quite possibly need TWO basevalues that control the shape of the curve. (Two magnets if you will). For example, the increase should be slower in the beginning, and increase more dramatically when we're reaching maxValue.

Can one of you math geniuses help me with an example function or perhaps give me some friendly pointers I suspect I have to combine Math.Log or Math.Pow with perhaps Math.Sin!

Thanks for any help!

//Sire



Re: Algorithm for getting a value from a dynamic logarithmic scale?

OmegaMan


One suggestion remember that double values are not exact and lose their accuracy around 15 significant digits. If more accuracy is needed use Decimal.





Re: Algorithm for getting a value from a dynamic logarithmic scale?

sirjis

It seems like there are a few different things going on with this function you are describing.

The first issue is a way to continuously go between a log function and an exponential function. (like the "base" parameter you describe, which doesn't really have anything to do with the base of the logarithm, if I understand correctly). I can't think of a function off of the top of my head that does this besides just interpolating between the two functions. So, I just spent an hour trying to figure this problem out...I came up with a solution, but you're not going to like it much, at least I don't.

So my simplified problem is as follows:

Given: x (unscaled value), q (curvature factor), b (logarithm base)
Find f(x, q, b) where q is the variable such that
  • q = -1 gives log_b(x) (the base b logarithm)
  • -1 < q < 0 gives the function which consists of points that are the weighted average along a line with slope -1 between the logarithm function and the line (a diagonal type of weighted average...I know this isn't very clear)
  • q = 0 gives x
  • 0 < q < 1 gives a similar weighted average between the line and the exponential function
  • q = 1 gives b^x
I drew some pictures and did some algebra, and unfortunately, got to something that is not closed form. I used Maple to figure out what function it is.

For q < 0: (q in all of these equations is actually |q|, i.e., -q)

f(x, q, b) = a*(1-q) + log_b(a)*(1+q)

where a = e^((b*(1-q)-2*x*ln(b))/(q-1));
where b = LambertW(ln(b)*(1+q)*b^(-2*x/(q-1))/(q-1));

LambertW is the Lambert W-Function, which (according to the Wolfram site I linked to) can be approximated well as

LambertW(z) = L_1 - L_2 + (L_2)/(L_1) + (L_2(-2+L_2))/(2L_1^2) + (L_2(6-9L_2+2L_2^2))/(6L_1^3) + (L_2(-12+36L_2-22L_2^2+3L_2^3))/(12L_1^4) + (L_2(60-300L_2+350L_2^2-125L_2^3+12L_2^4))/(60L_1^5)

where L_1 = ln(z) and L_2 = ln(ln(z)).

I didn't finish it for q > 0.

Okay, this is pretty complicated for what you're trying to do...sorry about that. I was hoping it would be a nice solution.

Just to make sure you're still interested in this problem before I do any more work, I'll wait for you to reply before I do the solution for q > 0 and give you the code. (This is fun for me, so don't worry about that).

Also, if I've misunderstood something in your problem, let me know. To clarify, what I've been working on so far is a function that can blend nicely between a logarithmic function and a linear function.





Re: Algorithm for getting a value from a dynamic logarithmic scale?

Matthew Watson

Actually, I wouldn't recommend using the Decimal type for this kind of calculation. Decimal is really intended for financial calculations, and it is awfully slow. It also doesn't give you such a large range of values.

Decimal is limited to ¡À1.0 ¡Á 10e 28 to ¡À7.9 ¡Á 10e28
Double ranges from -1.79769313486232e308 to +1.79769313486232e308

Where you are doing logarithmic calculations, you might very well want that extra range.

Not only that, but Math.Log() and Math.Pow() don't even have overloads that take Decimal parameteres...










Re: Algorithm for getting a value from a dynamic logarithmic scale?

Sire404

Wow, thanks a lot for dedicating so much time to my little problem!

I didn't notice anyone had replied here, so I just used this function:

public static double Scale(double value, double base1, double base2) {

return (Math.Log(value, base1) * Math.Pow(value, base2)) / 10D;

}

And fed it with two "base" values I calculated beforehand in another application.

However, this doesn't really work as I described, and your solution sounds very interesting!! Please do continue if you have the time, I would very much like to try out the resulting function!

Is it possible to implement the maxvalue as described

Thanks,

//Sire