InternalRateOfReturn の結果とエクセルのIRR関数の結果を比較すると
値が異なる場合があります
エクセルでは+なのですが InternalRateOfReturn ではーになります。
数値を変えてみた結果、エクセルのほうが正しいように思えます
何かよい解決方法はありませんか
InternalRateOfReturn関数を使用したことがないのですが、具体的な値を示していただくとお答えできるかもしれません。
結果が違うのなら、自前でルーチンを作成する必要が出てくるかもしれませんね。
IRR := internalRateOfReturn(0,[-111586,
42161,39619,39576,39576,37572,
37654,37470,35772,35654,-184712]);
エクセルでは0.272741ですがDELPHIでは-0.07536435となります
最初の引数Guessを0.2にすれば正しく表示されました
Flag := False;
for i := 8 downto 0 do
begin
Guess := i * 0.1;
IRR := internalRateOfReturn(Guess,
[S0,S1,S2,S3,S4,S5,S6,S7,S8,S9,S10]);
if (IRR >= Ges) and (IRR < Ges + 0.1) then
begin
Flag := True;
Break;
end;
end;
で一応は正しい値が帰ってきますが、Guessの値が戻り値とかけ離れている場合、エラーになりはしないか気がかりです
下のコードを実行すると、結果は2種類の値にわかれますね。
この場合なら、負の数は間違った計算結果ということになりますが、
Guessの値によって間違った計算結果が出るのは内部計算のバグなんでしょうか…
procedure TForm1.Button1Click(Sender: TObject);
var
Guess, IRR : Extended;
begin
Guess := 20;
while True do begin
IRR := internalRateOfReturn(Guess, [-111586,
42161,39619,39576,39576,37572,
37654,37470,35772,35654,-184712]);
ListBox1.Items.Add(Format('%8.5f ⇒ %18.15f',[Guess, IRR]));
if Guess > 1 then Guess := Guess - 1
else
if Guess > 0.11 then Guess := Guess - 0.01
else
if Guess > 0.05 then Guess := Guess - 0.0001
else break;
end;
end;
internalRateOfReturn はニュートンの解法により近似値を計算しています
ニュートンの解法の理論はわかりません。力学で、予想値から、方程式を解いていく問題をしたこととがあります。そのとき、予想値がかけ離れていると回答不能になりました。また、解が2つ出てくる場合もあり、誤っているほうは捨てることになります。
internalRateOfReturn では、誤っている解が選択されたのではないかと思うのですが。
う〜むさんのコードでGuessに20を代入してもエラーにならないことがわかりました。internalRateOfReturn の Guessを 0 から 0.5にしているためおそらくエラーは起こらないとは思うのですが
Delphi, Excelのバージョンはいくつですか?
こちらの環境(Delphi7Pro, Excel2000SP3)では、
Excel: -0.07536435 (小数点以下8桁に丸めた場合)
Delphi: -0.07536435 (小数点以下8桁に丸めた場合)
と出ますよ。
Excelでは、上で示していただいた値を、
[A列]
1: -111586
2: 42161
3: 39619
4: 39576
5: 39576
6: 37572
7: 37654
8: 37470
9: 35772
10: 35654
11: -184712
12: =IRR(A1:A11,0)
として表示しました。
IRRは複数の解答を持つそうで、その場合、ニュートン法の初期値によっては違う値を返します。
そのために、Guess引数(Delphiの場合は第1引数、Excelの場合は第2引数)で推測値を設定します。
ニュートン法の処理によっては、どちらかの解に振れてしまうこともありそうですし。
どうもありがとうございました。
戻り値と推定値を比較して正しい解を見つけるという方法を取りました
ツイート | ![]() |