我正在努力提高我的即将发布的作业的编程技能,它涉及解决问题,同时使其尽可能高效地运行。我知道这是一个相当克制/小块的代码,但如果有什么能使它运行得更快。
该方法采用一个包含事务详细信息的数组,有100个用于维护循环的事务数。所以我得到平均数量的股票,然后返回它。不能流利的英语,所以希望它有意义,谢谢
double Analyser::averageVolume()
{
// Your code
double averageNumShares = 0;
for(int i = 0; i < nTransactions; i++)
{
averageNumShares += tArray[i].numShares;
}
averageNumShares = averageNumShares / nTransactions;
return averageNumShares;
//return 0
}
答案 0 :(得分:4)
如果您需要计算n个数字的平均值,我担心您无法在示例代码中超过线性时间approch加速...
除非将其用作另一个更复杂的算法的一部分,在这个算法中你可能无需计算平均值或沿着这些线的某些东西,所以取平均值将是一个O(n)运算基本上涉及将数组的所有元素和一个除以元素的数量相加。这正是你所拥有的。
答案 1 :(得分:1)
为什么没有对象的另外两个值 - 运行总计和项目数?
然后计算平均值就可以利用这些数字。快速简单(可以是内联函数!)。
答案 2 :(得分:1)
这是一种额外的方法,类似于Ed Heal建议的方法,应该对舍入误差不太敏感。平均值的舍入误差随着累积和的大小而增加。这对您来说可能是也可能不是问题,但需要注意这一点。
这是一个迭代算法,可以最小化平均值中的舍入误差,这是我在Ross的旧版本(大约1998年)中首次遇到的:
double Analyser::averageVolume()
{
double averageNumShares = 0.0;
for (int i = 0; i < nTransactions; i++)
{
double delta = (tArray[i].numShares - averageNumShares) / (i+1);
averageNumShares += delta;
}
return averageNumShares;
}
这通过导出平均值的递归定义来实现。也就是说,给定样本x[1]
,...,x[j]
,...,x[N]
,您可以计算样本{{1}中的第一个M+1
样本的平均值和第一个x[M+1]
样本的平均值:
M
要了解两种方法的舍入误差,请尝试计算10 ^ 7个样本的平均值,每个样本等于1035.41。您的原始方法返回(在我的硬件上),平均值为1035.40999988683。上面的迭代方法返回1035.41的精确平均值。
不幸的是,两者在某些时候都是O(N)。您的原始方案有N个添加和一个分区。迭代方案有N个加法,减法和除法,因此您需要为准确性付出更多。答案 3 :(得分:0)
如果使用gcc更改优化级别。
答案 4 :(得分:0)
简短回答: 这段代码与速度一样好。您可以调整的是如何编译它。或者显然,如果这是一个选项,请在汇编中重写它。
“拉伸”答案: 现在......如果你真的想尝试获得更好的性能,已经尝试过使用所有可用的编译器优化标志和优化,并且你已经准备好以更快的速度来破坏代码可读性,那么可以考虑重写:
for(int i = 0; i < nTransactions; i++)
{
averageNumShares += tArray[i].numShares;
}
作为
pointerValue = &(tArray[0].numShares);
pointerIncrement = sizeof(tArray[0]);
for(int i = 0; i < nTransactions; i++)
{
averageNumShares += *(pointerValue++pointerIncrement);
}
通过显示编译器,您可以在每次循环迭代时跳过固定的偏移量,从而获得更好的性能。一个好的编译器应该能够看到你的初始代码。新代码可能会让您的性能更差。这实际上取决于编译器的具体情况,并且我不建议使用这种方法,除非您迫切希望获得比编译器提供的更好的性能,并且不希望跳转到使用内联汇编或内部函数(如果任何可用的。)
答案 5 :(得分:0)
int i= nTransactions;
while(i--){// test for 0 is faster
averageNumShares += (q++)->numShares;// increment pointer is faster than offset
}