我想使用std::numeric
的算法来计算数组绝对值的总和,以便使用gnu并行扩展(数组大小> 500000)。
这是我目前的代码:
double ret = 0;
for (auto i = 0U; i < length; ++i)
{
ret += std::abs(tab[i]);
}
return ret;
所以我想到了:
auto sumabs = [] (double a, double b)
{
return std::abs(a) + std::abs(b);
}
std::accumulate(tab, tab + length, 0, sumabs);
但它效率低下,因为如果执行简化算法(我真诚希望为了快速计算!),std::abs
将应用于已经> = 0的值。
有没有办法做到这一点?也许“手工”执行减少的第一步,让std::accumulate
在其余部分之间做一个简单的补充?但会有副本和内存命中......
答案 0 :(得分:1)
您可以将函数传递给accumlate方法并在函数内执行“手动”评估。顺便提一下,在代码中将abs方法应用于第一个参数,这是不必要的。
int fAccumulate (int accumulated, int accumulateIncrement)
{
int retValue = 0;
if (accumulateIncrement >= 0)
{
retValue = accumulated + accumulateIncrement;
}
else
{
retValue = accumulated + std::abs(accumulateIncrement);
}
return retValue;
}
使用此代码可能是:
int init = 0;
int numbers[] = {10,20,-30};
int a = std::accumulate (numbers, numbers+3, init, fAccumulate);
答案 1 :(得分:0)
这将使用对std::abs
的最少呼叫次数:
#include <algorithm>
#include <cmath>
int main() {
static const auto abssum = [] (auto x, auto y) {return x + std::abs(y);};
float entries[4] = {1.0f, 2.0f, 3.0f, 4.0f};
auto sum = std::accumulate(std::begin(entries), std::end(entries), entries[0], abssum) - entries[0];
}
也就是说,如果entries[0]
为正,则需要减去它;如果为负,则在std::accumulate
中抵消,并且此后也需要减去。