Javascript IRR(内部收益率)公式准确度

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15089151/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 23:27:07  来源:igfitidea点击:

Javascript IRR (Internal rate of return) Formula Accuracy

javascriptjqueryexcelmathexcel-formula

提问by dciso

I'm using a IRR function in javascript to create calculation a that is done in excel using its own IRR function. The problem is mine is little off and I have no idea why. Here's the code below.

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

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;
}

Now if you use these figures:

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



Period 24

第 24 期

Financed 22000

融资 22000

Rental 1017.5000

租金 1017.5000

My Result is: 0.008523000000000175

我的结果是:0.008523000000000175

Excel Result is: 0.008522918

Excel 结果为:0.008522918



OR

或者



Period 42

第 42 期

Financed 218000

融资218000

Rental 5917.1429

租金 5917.1429

My Result is: 0.006247000000000489

我的结果是:0.006247000000000489

Excel Result is: 0.00624616

Excel 结果为:0.00624616



The Excel function is called: =IRR(T12:T73,0.01)T12-T73 is the same figures I'm using.

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

Any help would be much appreciated, Thanks Jason

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

UPDATE

更新

I've solved it by changing the values below. But now the performance is too slow. Any ideas on how to improve this?

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

IRRCalc(IRRval, 0.001)

//to

IRRCalc(IRRval, 0.0001)

inc = 0.000001;

//to

inc = 0.00000001;

回答by whitneyit

After a quick skim read through your code, the error seems to be related to floating point precision error. More information can be found here: http://ajaxian.com/archives/crock-on-floating-points-in-javascript

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

In older javascript engines, if you did 0.3 + 0.3 you get something like 0.600000000001

在旧的 javascript 引擎中,如果你做了 0.3 + 0.3 你会得到类似 0.600000000001 的东西

Though most javascript engines today return 0.6, under the hood, the problem remains. Adding floats together causes unexpected results. So in your case the

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

inc = 0.000001;
guest += inc;

seems to me, to be the problem.

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

A way to solve this would be to use whole numbers. So instead of 0.000001 you would use 1 and instead of 0.001 you would use 1000. Then divide your return result by 100000

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

回答by Zohaib

We modified the code to achieve performance and accuracy. Try this:

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

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;
}

回答by Ben Lesh

It's a floating point issue to be sure. You're going to want to use a library like BigDecimal.jsto handle your values. It's really the only way to avoid this issue.

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

回答by Zulfugar Ismayilzadeh

Try this.

试试这个。

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;
}

回答by HattrickNZ

I would like to build on from @Zohaib Answer, but what I would like to do is show undefined where appropriate. The best I can do is get it to equal to zero. I am using this simple dataset irr_arr=[-100, 100, 100, 100, 100,100]. I would appreciate some advice.

我想以@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")}
}

this is the output

这是输出

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

here is the excel of what I am trying to produce

这是我正在尝试制作的优秀作品

enter image description here

在此处输入图片说明

回答by Set F

Don't set your min IRR to 0. That is what bounds your answer. Try allowing it to go negative. Also don't try to calc an IRR on one number.

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