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
Javascript IRR (Internal rate of return) Formula Accuracy
提问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
这是我正在尝试制作的优秀作品
回答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。