tags:

views:

64

answers:

2

How would i turn the secant method of iteration into php?

The formula is xi+1= xi - (f(xi) (xi-xi+1))/f(xi)-f(xi-1)

where f = function and i is an iteration.

so xi+1 is the next iteration after xi

So far I have seen this, but there is somethning wrong somewhere in it so i want to make one from scratch, unless someone here can see what is wrong with it?

while ((abs($y0 - $y1) > FINANCIAL_ACCURACY) && ($i < FINANCIAL_MAX_ITERATIONS))
  {
   $rate = ($y1 * $x0 - $y0 * $x1) / ($y1 - $y0);
   $x0 = $x1;
   $x1 = $rate;

   if (abs($rate) < FINANCIAL_ACCURACY) {
    $y = $pv * (1 + $nper * $rate) + $pmt * (1 + $rate * $type) * $nper + $fv;
   } else {
    $f = exp($nper * log(1 + $rate));
    $y = $pv * $f + $pmt * (1 / $rate + $type) * ($f - 1) + $fv;
   }

   $y0 = $y1;
   $y1 = $y;
   $i++;
  } 

Thanks

forgot to add, FINANCIAL_ACCURACY is defined as

define('FINANCIAL_ACCURACY', 1.0e-6);
A: 

First off, are you sure about the formula? I have a feeling that the right-most i+1 should be i-1. If not, you should start by rewriting the formula so that x[i+1] only shows up on the left.

Secondly, I'm unable to see how the code you posted implements the given formula. This page contains a number of secant method implementations you could easily port to php.

Michael Clerx
The code posted is basically a part of the code that I posted here http://stackoverflow.com/questions/3198939/recreate-excel-rate-function-using-newtons-method in response to a question on replicating Excel's RATE() function in PHP. I'm interested in knowing what's wrong with it, but the OP doesn't give much indication of any error
Mark Baker
the i+1 in the top part should be -1 sorry.by viewing the other code you linked to i found out the error : )define('FINANCIAL_ACCURACY', 1.0e-6); should bedefine('FINANCIAL_ACCURACY', 1.0e-8);
Jamie
A: 

Have been trying to use the following code

<?php
define('FINANCIAL_MAX_ITERATIONS', 20); 
define('FINANCIAL_PRECISION', 1.0e-08); 


function RATE($nper, $pmt, $pv, $fv = 0.0, $type = 0, $guess = 0.1) { 

    $rate = $guess; 
    if (abs($rate) < FINANCIAL_PRECISION) { 
        $y = $pv * (1 + $nper * $rate) + $pmt * (1 + $rate * $type) * $nper + $fv; 
    } else { 
        $f = exp($nper * log(1 + $rate)); 
        $y = $pv * $f + $pmt * (1 / $rate + $type) * ($f - 1) + $fv; 
    } 
    $y0 = $pv + $pmt * $nper + $fv; 
    $y1 = $pv * $f + $pmt * (1 / $rate + $type) * ($f - 1) + $fv; 

    // find root by secant method 
    $i  = $x0 = 0.0; 
    $x1 = $rate; 
    while ((abs($y0 - $y1) > FINANCIAL_PRECISION) && ($i < FINANCIAL_MAX_ITERATIONS)) { 
        $rate = ($y1 * $x0 - $y0 * $x1) / ($y1 - $y0); 
        $x0 = $x1; 
        $x1 = $rate; 

        if (abs($rate) < FINANCIAL_PRECISION) { 
            $y = $pv * (1 + $nper * $rate) + $pmt * (1 + $rate * $type) * $nper + $fv; 
        } else { 
            $f = exp($nper * log(1 + $rate)); 
            $y = $pv * $f + $pmt * (1 / $rate + $type) * ($f - 1) + $fv; 
        } 

        $y0 = $y1; 
        $y1 = $y; 
        ++$i; 
    } 
    return $rate; 
}   //  function RATE()

$rate = RATE(120,-331.09,20000);

print_r($rate);

?>

very strange, if you put some values in as the monthly payment it works perfectly, but then when you put others in it does not work.

the -331.09 does not work

i am trying to work out why it would work for some but not all numbers, when on excel the same values work perfectly

edit:

the problem is the FINANCIAL_PRESICION which is defined at the top. for some numbers it works as 08, for others it needs 03 or 04, problem is, how to make it so it does that automatically as the right number?

Jamie