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

我在javascript中使用一个IRR函数来创build一个在Excel中使用自己的IRR函数完成的计算。 问题是我的一点closures,我不知道为什么。 这是下面的代码。

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与我正在使用的数字相同。

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

UPDATE

我已经通过更改下面的值来解决它。 但现在的performance太慢了。 任何想法如何改善这一点?

 IRRCalc(IRRval, 0.001) //to IRRCalc(IRRval, 0.0001) inc = 0.000001; //to inc = 0.00000001; 

在快速浏览代码后,错误似乎与浮点精度错误有关 。 更多信息可以在这里find: 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; 

在我看来,是这个问题。

解决这个问题的方法是使用整数。 所以,而不是0.000001,你会使用1,而不是0.001,你会使用1000.然后划分你的返回结果100000

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

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

这是一个浮点问题。 你将要使用像BigDecimal.js这样的库来处理你的值。 这是避免这个问题的唯一方法。

尝试这个。

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

我想build立从@Zohaib答案,但我想要做的是在适当的地方显示undefined。 我能做的最好的是让它等于零。 我正在使用这个简单的数据集irr_arr=[-100, 100, 100, 100, 100,100] 。 我将不胜感激一些build议。

 //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 

这是我想要创造的

在这里输入图像说明

不要把你的最小IRR设置为0.这就是你的答案。 尝试让它消极。 也不要尝试在一个数字上计算IRR。