8

我在 javascript 中使用 IRR 函数来创建计算 a,该计算是在 excel 中使用其自己的 IRR 函数完成的。问题是我的问题不大,我不知道为什么。这是下面的代码。

var IRRval = [];

IRRval.push(-financed);
for (i = 0; i < period; i++) {
    IRRval.push(rental);
}

var IRR = IRRCalc(IRRval, 0.001) * 0.01;

function IRRCalc(CArray, guest) {
    inc = 0.000001;
    do {
        guest += inc;
        NPV = 0;
        for (var j=0; j < CArray.length; j++) {
            NPV += CArray[j] / Math.pow((1 + guest), j);
        }
    } while (NPV > 0);
    return guest * 100;
}

现在,如果您使用这些数字:


第 24 期

融资22000

租金 1017.5000

我的结果是:0.008523000000000175

Excel 结果为:0.008522918


或者


第 42 期

融资218000

出租 5917.1429

我的结果是:0.006247000000000489

Excel 结果为:0.00624616


调用 Excel 函数:=IRR(T12:T73,0.01)T12-T73 与我使用的数字相同。

任何帮助将不胜感激,谢谢杰森

更新

我已经通过更改下面的值来解决它。但是现在性能太慢了。关于如何改进这一点的任何想法?

IRRCalc(IRRval, 0.001)

//to

IRRCalc(IRRval, 0.0001)

inc = 0.000001;

//to

inc = 0.00000001;
4

7 回答 7

12

我们修改了代码以实现性能和准确性。试试这个:

function IRRCalc(CArray) {

  min = 0.0;
  max = 1.0;
  do {
    guest = (min + max) / 2;
    NPV = 0;
    for (var j=0; j<CArray.length; j++) {
          NPV += CArray[j]/Math.pow((1+guest),j);
    }
    if (NPV > 0) {
      min = guest;
    }
    else {
      max = guest;
    }
  } while(Math.abs(NPV) > 0.000001);
  return guest * 100;
}
于 2013-10-24T07:59:57.113 回答
9

快速浏览您的代码后,错误似乎与浮点精度错误有关。更多信息可以在这里找到:http: //ajaxian.com/archives/crock-on-floating-points-in-javascript

在较旧的 javascript 引擎中,如果您执行 0.3 + 0.3,您会得到类似 0.600000000001

尽管今天大多数 javascript 引擎返回 0.6,但问题仍然存在。将浮点数加在一起会导致意外结果。所以在你的情况下

inc = 0.000001;
guest += inc;

在我看来,这是问题所在。

解决这个问题的一种方法是使用整数。因此,您将使用 1 而不是 0.000001,而不是 0.001,您将使用 1000。然后将返回结果除以 100000

于 2013-02-26T12:36:06.680 回答
2

试试这个。

function NPV(discountRate, cashFlow){
    var npv = 0;
    for(var t = 0; t < cashFlow.length; t++) {
        npv += cashFlow[t] / Math.pow((1+ discountRate),t);
    }
    return npv;
}


function IRR(cashFlow,guess){
    guess = guess ? guess : 0.1;
    var npv;
    var cnt = 0;
    do
    {
        npv = NPV(guess,cashFlow);
        guess+= 0.001;

        cnt++;
    }
    while(npv > 0)

    return guess;
}
于 2013-05-27T17:50:02.927 回答
1

可以肯定的是,这是一个浮点问题。您将需要使用BigDecimal.js 之类的库来处理您的值。这确实是避免这个问题的唯一方法。

于 2013-02-26T14:44:21.523 回答
1

我想以@Zohaib Answer 为基础,但我想做的是在适当的地方显示未定义。我能做的最好的就是让它等于零。我正在使用这个简单的数据集irr_arr=[-100, 100, 100, 100, 100,100]。我会很感激一些建议。

//IRRCALC funtion that handles irr going to infinity 

function IRRCalc_test(CArray) {

  min = 0.0;
  max = 1.0;
  c=0;
  do {
    guest = (min + max) / 2;
    NPV = 0;
    for (var j=0; j<CArray.length; j++) {
          NPV += CArray[j]/Math.pow((1+guest),j);
    }
    if (NPV > 0) {
      min = guest;
      c++; 
    }
    else {
      max = guest;
      c++;
    }

    if(c>=15){ return guest*100; }
  } while(Math.abs(NPV) > 0.000001);
  return guest*100;
}


// some testing 

irr_arr=[-100, 100, 100, 100, 100,100]
irr_res_arr_expected=[0,0,61.8,83.93,92.76,96.6]
for(i=1;i<=irr_arr.length;i++){
console.log("irr_arr - ",irr_arr.slice(0,i));
console.log("IRRCalc - ",IRRCalc(irr_arr.slice(0,i)))
//console.log("irr_expected - ", irr_res_arr_expected[i-1])
//if(IRRCalc(irr_arr.slice(0,i))===parseFloat(irr_res_arr_expected[i-1]).toFixed(2)){console.log(i,"- TRUE")} else {console.log(i,"- FALSE")}
}

这是输出

irr_arr -  [-100]
IRRCalc -  0.00      <<<<<<<<<<<<<<<<<<<------- this should be 'undefined' and not 'zero'
irr_arr -  [-100, 100]
IRRCalc -  0.00
irr_arr -  [-100, 100, 100]
IRRCalc -  61.80
irr_arr -  [-100, 100, 100, 100]
IRRCalc -  83.93
irr_arr -  [-100, 100, 100, 100, 100]
IRRCalc -  92.76
irr_arr -  [-100, 100, 100, 100, 100, 100]
IRRCalc -  96.60

这是我想要制作的优秀作品

在此处输入图像描述

于 2015-12-20T22:45:42.153 回答
0

不要将您的最小 IRR 设置为 0。这就是您的答案的界限。试着让它变成负面的。也不要试图计算一个数字的内部收益率。

于 2016-02-21T12:10:35.513 回答
0

这可能是编写计算的更好方法。这允许代码计算负 IRR 或 IRR 高于 100% 的实例。

        var IRRval = [];

        IRRval.push(-financed);
            for (i = 0; i < period; i++) {
            IRRval.push(rental);
        }
        var IRR = IRRCalc(IRRval, 0.001) * 0.01;

        function IRRCalc(CArray) {
            var r = 0
            min = -1.0;
            max = 10000.0;
            do {
                guest = (min + max) / 2;
                NPV = 0;
                for (var j = 0; j < CArray.length; j++) {
                    NPV += CArray[j] / Math.pow((1 + guest), j);
                }
                if (NPV > 0) {
                    min = guest;
                }
                else {
                    max = guest;
                }
                r++
            } while (r < 100);
            return guest * 100
        }
于 2020-09-14T16:03:48.857 回答