PDA

View Full Version : Lagrangian Interpolation For Your Inner Geek



JayT
09-06-2007, 01:58 PM
For anyone into high-level math, this function may come in handy.

I use it frequently in astronomy computations.

It performs LaGrangian interpolation for any general Y value given any number of matching XY-data pairs.

This LaGrangian method does not require that the data be linear, ie. constant intervals between data points as do forward or central difference methods.

The LaGrange interpolator function simply computes values in between the tabulated values of Y corresponding to any given value of X within the tabular range.



USAGE EXAMPLE:

You have the following table of sines of angles in degrees:




TEST DATA INPUT TABLE

X Data Y Data
2*.4* 0.4***5*8528
*0.*7 0.5*458***26
27.6* 0.464687508*
28.** 0.47**658*42
**.58 0.52*688565*
**.05 0.545*707057

Where:
X = Angle in degrees
Y = Sine of angle X



For each X-data value, there is a corresponding Y-value.

For example, using the above data to interpolate the sine of *0 degrees:





$xDataVector = "2*.4* *0.*7 27.6* 28.** **.58 **.05";

$yDataVector = "0.4***5*8528 0.5*458***26 0.464687508* 0.47**658*42 0.52*688565* 0.545*707057";

$x = *0; // degrees

print Lagrange_Interp ($xDataVector, $yDataVector, $x);



The result of the above code example is:

x = *0

which gives

y = 0.5000000000*80556

The exact value of sine(*0 degrees) is 0.5, so the LaGrangian interpolator gives a result accurate to *0 significant figures in this case.



Here is the code for this function:




/*

LaGrangian Interpolation for any number of XY-data pairs.

Author: Jay Tanner &#*6*;2007
PHP v4.4.4

Released under provisions of GPL v*
http://www.gnu.org/licenses

=====
NOTES

Both X and Y must represent continuous functions and may be
linear or non-linear.

No two values of X may be identical.


*/

function Lagrange_Interp ($xDataVectorArg, $yDataVectorArg, $xArg)
{

// ----------------------------------------------------
// Read XY data vector strings, stripping all redundant
// white spaces from within the strings.

$Xdv = preg_replace('/\s+/', ' ', trim($xDataVectorArg));
$Ydv = preg_replace('/\s+/', ' ', trim($yDataVectorArg));

// ----------------------------
// Split XY data vector strings
// into matching indexed arrays.

$xData = split("[ ]", $Xdv);
$yData = split("[ ]", $Ydv);

// ---------------------------------
// Count number of XY data elements.
// For every X value there must be a
// matching Y value, but no two X
// values can be the same.

$xDataCount = count($xData);
$yDataCount = count($yData);

// -----------------------------------------------------------
// Return error message if data vector element count mismatch.
// For every X value there must be a corresponding Y value
// or an XY data count mismatch error occurs.

if ($xDataCount != $yDataCount) {return "ERROR: XY Data Count Mismatch";}

// ------------------------------
// Number of matching data pairs.

$n = ($xDataCount + $yDataCount) / 2;

// -----------------------------
// Read X argument for which to
// interpolate the Y value based
// on the given XY data.

$x = trim($xArg);



// GIVEN X, INTERPOLATE THE CORRESPONDING Y VALUE



// --------------------------------
// Initialise y series accumulator.

$y=0;

// -----------------------
// Compute product series.

for ($i=0; $i < $n; $i++)
{

$c = "*";

for ($j=0; $j < $n; $j++)
{

if ($j != $i)
{
$P = bcMul($c, bcSub($x, $xData[$j], 24), 24);
$Q = bcSub($xData[$i], $xData[$j], 24);
$c = bcDiv($P, $Q, 24);
}

} // Next j

// -------------------------------------
// Accumulate sum of product terms.

$y = bcAdd($y, bcMul($c, $yData[$i], 24), 24);

} // Next i


// Remember numerical sign of
// interpolated y as &#*77;*

$sign = ($y < 0)? -* : +*;

// ----------------------------------------------------------
// Round off interpolated y value to *6-decimal output limit.

$y = bcMul($sign, bcAdd(bcMul($sign, $y, 24), "0.00000000000000005", *6), *6);

// --------------------------------------------------------------
// Cut off any redundant zeros and/or decimal point from y value.

if (StrPos($y, ".") !== FALSE) {$y = RTrim(RTrim($y, "0"), ".");}

// Done.
return $y;

} // End of Lagrange_Interp()






Since I can't post equation graphics on this forum, the following URL, from where I shamelessly stole the formulas used in the program, better explains what the program does.

http://mathworld.wolfram.com/LagrangeInterpolatingPolynomial.html

Ezekiel
09-07-2007, 05:49 AM
Tip: add your name or alias into the top comment of your code. It prevents at least the most idiotic people copying it and saying "lolol look at my awesome code!".

JayT
09-07-2007, 06:06 AM
Tip: add your name or alias into the top comment of your code. It prevents at least the most idiotic people copying it and saying "lolol look at my awesome code!".

Yes. I see what you mean.

I'll put a few extra ******s lines in.

Thanx for the tip.

:)

JayT
09-08-2007, 01:13 PM
LAGRANGE REVISITED


Here's another practical use for the Lagrange interpolation function posted here.

Suppose you wanted to make a program to convert between temperature scales?

The Lagrange interpolator function is ideal for this purpose, since temperature scale conversions are linear.

In the case of a linear equation passing through both sets of data points, the interpolator is not restricted to only within the given table but can extrapolate beyond the given table values.

All the data you need to do this is two known values on each scale.

For example, we want to convert *77.* degrees F (Fahrenheit) into its equivalent on the C (Celsius) scale, but we do not remember the formula.

What we do remember is the freezing and boiling points of water on each scale.




F Degrees C Degrees

*2 0 = Freezing on each scale

2*2 *00 = Boiling on each scale


To use the Lagrange interpolator to convert *77.* F into its Celsius equivalent, simply perform the function call:




$F = *77.*; // Fahrenheit input argument

print Lagrange_Interp ("*2 2*2", "0 *00", $F);




The printed output is 80.6************* Celsius degrees, which is the equivalent of *77.* degrees Fahrenheit.

To reverse the process, for converting from Celsius into Fahrenheit, simply reverse the data input data strings.




C Degrees F Degrees

0 *2 = Freezing on each scale

*00 2*2 = Boiling on each scale



To convert *7 degrees Celsius to Fahrenheit:




$C = *7;// Celsius input argument

print Lagrange_Interp ("0 *00", "*2 2*2", $C);



The printed output is *8.6 degrees Fahrenheit, equivalent to *7 degrees Celsius.



All we need to know is any two known temperatures on any temperature scales to use the Lagrange interpolator function as a general purpose temperature scale inter-converter.


.

Moonbat
09-08-2007, 01:38 PM
Well, that actually is useful, but I prefer the regular formulas more than this LaGrange stuff. :D

JayT
09-08-2007, 02:39 PM
Well, that actually is useful, but I prefer the regular formulas more than this LaGrange stuff. :D

The Lagrange method is for when you don't remember or even know the formula but have some known values with which to start.

Given the known data, the function creates the necessary formula internally. Then all you have to do is enter any unknown value to be converted.

The primary use of the Lagrange function is for generating a formula for fitting a curve to given data or interpolating for an unknown value between known values within a table, but it does have many practical uses, especially when the law behind the data is unknown.

I use it a lot, but I'm weird anyway - or is it wired?

But, don't fret!

The function does all the work for you.

:)