2012-04-07 11 views
1

を返す:私はrate(60, -6000, 120000)ような何かを呼び出すとhttp://pastebin.com/Sd9WKZFrPHPExcel基づく関数のRATE()私はこのコードを持っているNAN()

それは私にNAN結果を返しますが、MSエクセル上の同じ機能は私に0,04678...を返します。私は-5000、-4000、-3000、-2000を試してみても同じ問題があります。

私はコードをデバッグすると、私は8/9の反復について、行番号29はNANの結果を返し始め、他のすべての結果はNANにもなります。

しかし、私がrate(60, -1000, 120000)のようなものを呼び出すと、私はfloat -0.02044...のMS Excelと全く同じ結果を返します。

私はすでにBCMath機能に数学の計算のすべてを変換するためにしようと試みているが、この方法は、-6000の結果が間違っている(-1.0427 ...ではなく0,04678の...)が、使用して - 1000結果が正しい、Excelの結果と一致する。

正しく動作させる方法はありますか?

事前に感謝していただきありがとうございます。

+1

のみ3回の反復をとり、これは計算として、主に見えます問題。 - $ rateが負になる可能性がありますので、log()は29行目で定義されていませんか? - 角括弧は正しく設定されていますか? – worenga

+0

こんにちは@mightyuhu、それはうまく動作-1000を使用して原因sintaxeエラーはありません。同時に、安定したphpexcelからの関数です。とにかくありがとう。 – slinstj

+0

@sidtj @mightyuhuが正しく、 'rate(60、-6000、120000)'はRate <1の中間結果を生成します(これは8/9回目の繰り返しですでに識別されています)。あなたのアルゴリズムに取り組む必要があります –

答えて

2

他の状況で悪影響がないようにいくつかのテストを行う必要があります。しかし、以下では、それはこの問題を解決し、確かにあなたの引数のRATE(60、-6000、120000)の正しいレート値を計算可能性があるかのように見える、私は使用することをお勧めしません反復15.

define('FINANCIAL_MAX_ITERATIONS', 128); 
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 (($nper * abs($pmt)) > ($pv - $fv)) 
      $x1 = abs($x1); 

     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() 
+0

こんにちはベイカー、私はあなたにそれを送ったのを見たときにphpexcelフォーラムであなたにこのリンクを送ろうとしていました:あなた自身。 あなたの回答を受け入れる前に回してください。 – slinstj

+0

すでにいくつかのテストを行っています:それはあなたのレート(60、-1000、120000)の例ではうまく動作しません –

+0

何がうんざりですか?60,600,120000を使って0.046781916422493これは、LibreOffice Calcと同じ結果です(Excelでは、#NUMを返します)。しかし、abs()を使用しているこの関数の値が小さいほど、間違った結果が返されます。 貴重な努力をいただきありがとうございます。 – slinstj

1

に0.046781916422493で安定他の好ましい反復法、例えばニュートンラフソン法よりも多くの時間を消費するので、internal rate of returnを見つけるためのSecant法。 128回の反復の最大値を設定すると、時間2つのTVM方程式のいずれかでNewton Raphson method to find RATEを使用して

の無駄であると思われるコードから、これは単なるguessingsある

TVM Eq. 1: PV(1+i)^N + PMT(1+i*type)[(1+i)^N -1]/i + FV = 0 

f(i) = 0 + -6000 * (1 + i * 0) [(1+i)^60 - 1)]/i + 120000 * (1+i)^60 

f'(i) = (-6000 * (60 * i * (1 + i)^(59+0) - (1 + i)^60) + 1)/(i * i)) + 60 * 120000 * (1+0.05)^59 

i0 = 0.05 
f(i1) = 120000 
f'(i1) = 42430046.1459 
i1 = 0.05 - 120000/42430046.1459 = 0.0471718154728 
Error Bound = 0.0471718154728 - 0.05 = 0.002828 > 0.000001 

i1 = 0.0471718154728 
f(i2) = 12884.8972 
f'(i2) = 33595275.7358 
i2 = 0.0471718154728 - 12884.8972/33595275.7358 = 0.0467882824629 
Error Bound = 0.0467882824629 - 0.0471718154728 = 0.000384 > 0.000001 

i2 = 0.0467882824629 
f(i3) = 206.9714 
f'(i3) = 32520602.801 
i3 = 0.0467882824629 - 206.9714/32520602.801 = 0.0467819181458 
Error Bound = 0.0467819181458 - 0.0467882824629 = 6.0E-6 > 0.000001 

i3 = 0.0467819181458 
f(i4) = 0.056 
f'(i4) = 32503002.4159 
i4 = 0.0467819181458 - 0.056/32503002.4159 = 0.0467819164225 
Error Bound = 0.0467819164225 - 0.0467819181458 = 0 < 0.000001 
IRR = 4.68% 


TVM Eq. 2: PV + PMT(1+i*type)[1-{(1+i)^-N}]/i + FV(1+i)^-N = 0 

f(i) = 120000 + -6000 * (1 + i * 0) [1 - (1+i)^-60)]/i + 0 * (1+i)^-60 

f'(i) = (--6000 * (1+i)^-60 * ((1+i)^60 - 60 * i - 1) /(i*i)) + (0 * -60 * (1+i)^(-60-1)) 

i0 = 0.05 
f(i1) = 6424.2628 
f'(i1) = 1886058.972 
i1 = 0.05 - 6424.2628/1886058.972 = 0.0465938165535 
Error Bound = 0.0465938165535 - 0.05 = 0.003406 > 0.000001 

i1 = 0.0465938165535 
f(i2) = -394.592 
f'(i2) = 2081246.2069 
i2 = 0.0465938165535 - -394.592/2081246.2069 = 0.046783410646 
Error Bound = 0.046783410646 - 0.0465938165535 = 0.00019 > 0.000001 

i2 = 0.046783410646 
f(i3) = 3.1258 
f'(i3) = 2069722.0554 
i3 = 0.046783410646 - 3.1258/2069722.0554 = 0.0467819004105 
Error Bound = 0.0467819004105 - 0.046783410646 = 2.0E-6 > 0.000001 

i3 = 0.0467819004105 
f(i4) = -0.0335 
f'(i4) = 2069813.5309 
i4 = 0.0467819004105 - -0.0335/2069813.5309 = 0.0467819165937 
Error Bound = 0.0467819165937 - 0.0467819004105 = 0 < 0.000001 
IRR = 4.68% 
関連する問題