3

Excel のレート関数をエミュレートするために、svn から取得したApache POIレート関数を使用しています。

private double calculateRate(double nper, double pmt, double pv, double fv, double type, double guess) {

  //FROM MS http://office.microsoft.com/en-us/excel-help/rate-HP005209232.aspx
  int FINANCIAL_MAX_ITERATIONS = 20; //Bet accuracy with 128
  double FINANCIAL_PRECISION = 0.0000001; //1.0e-8

  double y, y0, y1, x0, x1 = 0, f = 0, i = 0;
  double rate = guess;
  if (Math.abs(rate) < FINANCIAL_PRECISION) {
     y = pv * (1 + nper * rate) + pmt * (1 + rate * type) * nper + fv;
  }
  else {
     f = Math.exp(nper * Math.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 the Newton secant method
  i = x0 = 0.0;
  x1 = rate;
  while ((Math.abs(y0 - y1) > FINANCIAL_PRECISION) && (i < FINANCIAL_MAX_ITERATIONS)) {
     rate = (y1 * x0 - y0 * x1) / (y1 - y0);
     x0 = x1;
     x1 = rate;

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

     y0 = y1;
     y1 = y;
     ++i;
  }
  return rate;

}

calculateRate(120, 28.1, -2400, 0, 0, 0.1)) の場合、出力は Excel と同じ: 0.599

しかし、同じ計算を試してみると、今度は値を使用して次のようになります。

calculateRate(360, 15.9, -2400, 0, 0, 0.1))

Excel では0.580を取得し、プログラムは-1.1500428517726355を返します。ヒントはありますか?

4

2 に答える 2

3

質問に貼り付けたこのコードには、多くの問題があります。

レートが常に (真ではない) 検出されると仮定し、レートが検出されない場合のインスタンスを提供しません。

一部のステートメントは、より適切なプログラミング ステートメントを使用することで回避できたエラーをスローします。たとえば、コードから次のステートメントを取得します。

f = Math.exp(nper * Math.log(1 + rate));

これにより、負またはゼロの値のログを見つけようとするとエラーがスローされます。のように書き換えることができた.

f = Math.pow(1 + rate, nper);

反復計算のコメントは、正割法をプログラミングしていると述べていますが、反復計算は間違った変数の収束をチェックしています。金利の収束をテストすべきところを、将来価値の収束をテストしています。

コードをコピーしてメモ帳に貼り付け、Java の変数宣言を削除し、これらを JavaScript 変数宣言に置き換えて、サンプル データでコードをテストしました。そして、私が言ったように、コードは 2 回目の反復で停止します。これは、将来の値の差がエラー バウンドを超えるためです。また、利率が見つかるかどうかを確認するテストが実施されていないため、コードは利率をそのまま返し、1 つを返します。これは間違っています。

最初のデータセットの場合のように、正しいレートを報告するインスタンスでこのコードが機能する理由はわかりません。関数を正しい方法で再コーディングすることをお勧めします。

于 2012-12-30T01:34:38.147 に答える
-1
public double rate(double nper, double pmt, double pv)
{
    //System.out.println("function rate : " + nper + " " + pmt + " pv " + pv);

    double error = 0.0000001;
    double high =  1.00;
    double low = 0.00;

    double rate = (2.0 * (nper * pmt - pv)) / (pv * nper);

    while(true) {
        // Check for error margin
        double calc = Math.pow(1 + rate, nper);
        calc = (rate * calc) / (calc - 1.0);
        calc -= pmt / pv;

        if (calc > error) {
            // Guess is too high, lower the guess
            high = rate;
            rate = (high + low) / 2;
        } 
        else if (calc < -error) {
            // Guess is too low, higher the guess.
            low = rate;
            rate = (high + low) / 2;
        } 
        else {
            // Acceptable guess
            break;
        }
    }

    //System.out.println("Rate : " + rate);
    return rate;
}

例: =RATE(60, 2112500, 65000000)0.025198 を返します。Excelでも同じです(正解)。

于 2014-01-30T06:15:38.620 に答える