My roommate Noah (Sir Noah S&F, Esq. to be precise) has found the fun of spreadsheets. We were talking a while back and he was tinkering with the spreadsheet trying to come up with a function. This function was suppose to curve like 1/x but cross through some given points (like 0,7 and 1,0). I told him how the function could simply be offset (1/x + c) and scaled (a/x) and so it would pass through those points. He told me to shut-up (the "all you need to do" answer from the math major dashed his grand view of the complexity of this challenge) and I more or less forgot about it. This morning, I was thinking about it and decided to implement something quick in a spreadsheet. The results were, well, not too interesting. I created the function and found b and c such that and . Variable d could be any positive number greater then 0.
The results were not interesting and probably not what Noah would have desired. The curve's slope changed with the value of d. For large values of d, the curve turned into almost an "L" shape. Small values of d resulted in almost a straight line. I don't know if that is what Noah had intended or not, but seeing the result started me thinking.
I was originally going to scale up "Noah's function" to take two points such that f(0)=d and f(1)=e. But the fact the curve changed slope made me wonder if I couldn't make the curve controlled. Well, the answer is "of course," but we will no longer have a 1/x type situation. In fact, we can get this curve using a second-degree polynomial. With 3 known points, we can use polynomial interpolation to determine the remaining points. I've written about polynomial interpolation in the past. But I wanted not just to plug numbers into an algorithm. Besides, as I recalled starting this, the solution to my problem will require matrix math :)
I don't actually know much matrix math. The calculus 2 class I just finished introduced cross-products, so determinants we briefly mentioned. Most of that was review for me since I had played with determinants in order to understand least-square quadratic curve fitting. I've never let what I don't yet know stop me though.
We can represent our second degree polynomial as . This function is sufficient to draw a curve that passes through 3 points. The one exception is that we can not define two or three points having the same x but different y values. So the points (0,1) (0,2) would not be possible, since the function can not have a value of 1 and 2 at 0. Otherwise, we can pick any arbitrary points we like.
For example sake, let's use (0,7) (2,3) and (5,0) as the known points. What this results in are three equations with three unknowns—a system of equations. y is the same as f(x), so each point is actually (x, f(x)). Thus, f(0)=7, f(2)=3 and f(5)=0. Expanded we get these three equations:
We can solve for a, b and c using basic algebra. When we do so, we will get values for a,b and c that will create a curve that passes through (0,7) (2,3) and (5,0). However, that is not a general solution—just the solution for these 3 example points. What we want is a function that will translate any 3 points into a,b,c. For this, we need a matrix.
To solve the above using a matrix, we get a matrix that looks like this:
Once we have the matrix form, we can solve. The approach I found shown the most was Gaussian elimination. While this method might work well on paper, it's not the easiest method to program. Luckily we have Cramer's rule, which is much easier to work with in code:
So we have working numbers for this specific case. However, what we need is a more general equation for any 3 points. Note that to form the series of equations filled in the known x and y into f(x) for each point. Let's redefine our points as variables and then construct a matrix from this.
System of equations
With the matrix equation in place, the determinants and finial results can be calculated.
That is not hard to code at all. So below is a real-time example of this in action. Here is the PHP source code for the example. It uses the library XY-Plot.