加速程序计算优化技术---记忆
在计算机领域,记忆是主要用于加速程序计算的一种优化技术,它使得函数避免重复演算之前已被处理的输入,而返回已缓存的结果。
在JS的对象和数组要实现这种优化是非常方便的。
下面用一个经典递归函数----斐波那契数列
var conut=0;
var fibonaccii = function (n)
{ conut++;
console.log("conut:" + conut);
return n< 2 ? n : fibonaccii(n-1) + fibonaccii(n-2);
};
function test() {
for (var i= 0; i <= 10; i += 1) {
console.log(i+":" + fibonaccii(i));
}
}
这样工作是可行的;但是效率非常低。我算了一下:
函数被调用了453次,我们调用了11次;所以,它自身递归调用442次,有很多是已经被刚刚计算过了;如果我们让函数具有记忆功能,就可以显著提高极少计算量,提高效率。
var count = 0;
var fibonaccii = function () {
var memo =[0,1];
var fib =function (n) {
count++;
console.log("count:" + count);
varresult = memo[n];
if(typeofresult !== ‘number‘) {
result= fib(n-1) + fib(n-2);
memo[n]= result;
}
returnresult;
};
returnfib;
}();
function test() {
for (var i= 0; i <= 10; i += 1) {
console.log(i+":" + fibonaccii(i));
}
}
test();
这个函数返回同样的结果,但是很明显,仅仅被调用了29次,我们自己调用了11次;也就只用了18次去取之前存储的结果;
当然,我们可以推而广之,编写一个函数来帮助,我们构造带记忆功能的函数,memoizer函数取得一个初始的memo数组和formua函数;它返回一个管理memo存储和在需要时调用fromula的函数recur;我们把这个函数recur函数和它的参数传递给formula函数
var memoizer = function (memo, formula) {
var recur= function (n) {
varresult = memo[n];
if(typeofresult !== ‘number‘) {
result= formula(recur, n);
memo[n]= result;
}
returnresult;
}
returnrecur;
};
现在,我们可以使用memoizer函数来定义fibonaccii函数,提供其初始的memo数组和formula函数;
var fibonaccii = memoizer([0,1],function (recur, n)) {
returnrecur(n - 1) + recur(n - 2);
});
通过这种设计方案,产生另一个函数的函数,极大地减少了我们工作量,例如,我们要产生一个记忆的阶乘函数,我们可以这样
var factorial = memoizer([0, 1], function (recur, n)){
returnn*recur(n - 1);
}
只需要提供基本的阶乘公式就可以了。