我对c ++很新,我想学习如何优化程序的速度。我目前正在研究一个计算从1到1.000.000的完美数字的程序。一个完美的数字是其适当除数的总和等于数字本身。例如。 28是完整数,因为1 + 2 + 4 + 7 + 14 = 28。以下是我的代码
#include <iostream>
using namespace std;
int main() {
int a = 1000000;
for(int i = 1; i <= a; ++i)
{
int sum = 0;
int q;
// The biggest proper divisor is half the number itself
if(i % 2 == 0) q = i/2;
else q = (i+1)/2;
for(int j = 1; j <= q; ++j)
{
if(i % j == 0) sum += j;
}
//Condition for perfect number
if(sum == i) cout << i << " is a perfect number!" << endl;
}
system("pause");
return 0;
}
此代码中的哪些操作非常耗时?如何提高程序的速度?一般来说,我如何了解耗时的操作以及如何避免这些操作?
答案 0 :(得分:2)
真正了解哪些操作耗时并且限制程序执行速度的唯一方法是通过分析器运行程序。此工具将告诉您每秒执行时间的消耗(通常基于函数调用)。
具体回答你的问题:这个程序中的大部分时间将用在这一行:
system("pause");
因为,除了你应该摆脱的一段可怕的代码之外,实际上是用户输入,而且众所周知,椅子和屏幕之间的东西会降低速度。
答案 1 :(得分:1)
您可以通过以下内容消耗计算交易:
const int max = 1000000;
std::vector<std::size_t> a(max);
for(std::size_t i = 1; i != a.size(); ++i) {
for (std::size_t j = 2 * i; j < a.size(); j += i) {
a[j] += i;
}
}
for (std::size_t i = 1; i != a.size(); ++i) {
if(a[i] == i) {
std::cout << i << " is a perfect number!" << std::endl;
}
}
答案 2 :(得分:0)
我的经验法则:
如何避免它们?
嗯,没有简单的答案。在许多情况下,你不能。
通过使用无分支表达式或改进程序逻辑来避免使用条件分支。
通过使用shift或lookup-tables或重写表达式(如果可能)来避免分裂。
通过模拟定点来避免浮点。
在给定的示例中,您必须关注最内层循环的主体。这是最频繁执行的行(约为125000000000次,而其他行则为1000000次)。不幸的是,有一个比较和分裂,很难删除。
代码其他部分的优化将没有可测量的效果。特别是,不要担心cout
声明:它总共会被调用4次。
答案 3 :(得分:0)
分支:if
s,循环,函数调用和goto
代价很高。它们往往会分散处理器对执行数据传输和数学运算的注意力。
例如,您可以删除if
语句:
q = (i + (i % 2)) / 2; // This expression not simplified.
研究循环展开,尽管编译器可以在更高的优化设置上执行此操作。
I / O操作成本很高,尤其是使用格式化的I / O. 试试这个:
if(sum == i)
{
static const char text[] = " is a perfect number!\n";
cout << i;
cout.write(text, sizeof(text) - 1); // Output as raw data.
}
分部和模数操作成本很高 如果你可以除以2的幂,你可以将除法转换为右移 您可以通过使用二进制AND来避免模运算。