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
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