为什么低效的阶乘计算…高效(快速)
Why inefficient factorial computation is...efficient (and fast)?
我写了这个简单的程序来测试记忆技术:
int main() {
function<double(double)> f = [&f](double i) -> double {
if (i == 1)
return 1;
else
return i * f(i - 1);
};
cout << f(100) << endl;
}
我本来希望在几秒钟内执行这段代码(因为它的递归效率很低),但实际上只花了几毫秒…为什么?我认为有一些编译器优化,但我不知道会发生什么。
奖金问题:你能给我一个简单的程序吗?它的执行效率很低(编译器优化与否),所以我可以测试记忆的好处?
记忆化技术旨在优化昂贵的函数调用。阶乘函数并非如此。C++速度极快,因此阶乘函数调用的计算时间永远不会超过几毫秒。(至少如果不使用多精度)。factorial(100)是"仅"100次乘法运算,因此对于C++没有任何运算。
如果这只是为了测试或演示的目的,我会简单地在函数调用中引入一个延迟(睡眠、长伪循环或其他什么)。随着记忆的实现,这种延迟不应该发生,所以它"几乎"很快就会运行。
这是我要做的一个例子。factory是一个昂贵的函数memory_factoral是它与所实现的存储技术的结合。在对函数的第一次调用中,输入和输出的字典会被更新,在接下来的具有相同输入的调用中,先前存储的值会被返回,因此"真实"函数不会再次执行。
#define ELAPSE(cmd) { clock_t s = clock();
long ret = cmd;
cout << "t" << #cmd
<< " = " << ret
<< "t(" << (clock()-s)/double(CLOCKS_PER_SEC) << " secs)"
<< endl; }
long factorial(long i) {
for(clock_t s = clock(); (clock()-s)<CLOCKS_PER_SEC; );
return i<=1 ? 1 : i*factorial(i-1);
}
long memo_factorial(long i) {
static map<long,long> saved;
map<long,long>::const_iterator it = saved.find(i);
return ( it==saved.end() ) ? (saved[i] = memo_factorial(i)) : it->second;
}
int main() {
cout << "first execution WITHOUT memoization" << endl;
for(int i=1; i<5; ++i) {
ELAPSE( memo_factorial(i) )
}
cout << "second execution WITH memoization" << endl;
for(int i=1; i<5; ++i) {
ELAPSE( memo_factorial(i) )
}
return 0;
}
输出应为:
first execution WITHOUT memoization
memo_factorial(i) = 1 (1 secs)
memo_factorial(i) = 2 (1 secs)
memo_factorial(i) = 6 (1 secs)
memo_factorial(i) = 24 (1 secs)
second execution WITH memoization
memo_factorial(i) = 1 (0 secs)
memo_factorial(i) = 2 (0 secs)
memo_factorial(i) = 6 (0 secs)
memo_factorial(i) = 24 (0 secs)
希望你觉得它有用。
谨致问候,Alex
注意:阶乘通常定义在整数值上。当然,它只是一个乘法序列,因此它可以应用于其他类型。
看看维基上关于动态编程的数字。第二张图中划掉的所有通话都是你从备忘录中节省的费用。有了阶乘函数,什么都不会被划掉。
相关文章:
- 大量序列中核苷酸类型的快速计数
- C++中高效的大型稀疏块压缩线性方程
- 为什么比较运算符如此快速
- C++中的高效循环缓冲区,它将被传递给C样式数组函数参数
- OpenCV C++.快速计算混淆矩阵
- 用C++快速读写文件
- 如何在C++中高效地构造随机骰子
- 位阵列上的快速AND运算
- 如何实现高效的算法来计算大型数据集的多个不同值?
- 更改命令行 qt5 源代码构建配置的正确/快速方法
- 在TFHE(完全快速同态加密)上执行除法
- 有没有一种优雅而快速的方法来测试整数中的 1 位是否位于连续区域
- 如何修复我的快速排序实现?
- 使用动态实例化的对象填充矢量的快速方法
- 按下特定键时快速按此键.如何防止按下扳机键?(C++)
- 是否有 C++/C 的高效构建功能可以快速均匀地对 b 条目进行采样,而无需替换 n 个条目?
- 为什么低效的阶乘计算…高效(快速)
- 快速编译高效的排序算法(用于JIT编译)
- 将结构数组写入文本文件的快速高效方法
- 在c++中更高效、更快速地反转矩阵(大矩阵和小矩阵)