我在我的程序中编写了一些数学函数,它们将得到非常大的使用。我想提供代码,看看a)是否有改进的逻辑和b)如果有更好的方法来做这些。它是一个头文件,包含在需要的地方。
我没有为c ++ 11编译,所以请记住这一点。 - 我也知道负数的rootDouble在数学上是不正确的。
我认为可能出现的第一件事就是将矢量输入转换为引用传递,欢迎使用这些注释。
就我接受答案而言,我想知道这些功能可以提高速度的方式和方式。
++我很快就发布了这个,希望我内心没有留下任何尴尬的错误!
#ifndef MATHSFUNCTIONS_H_
#define MATHSFUNCTIONS_H_
#include <algorithm>
#include <vector>
#include <numeric>
#include <cmath>
class MathsFunctions {
public:
MathsFunctions();
virtual ~MathsFunctions();
inline static double squareDouble(double input) {
return input * input;
}
inline static double rootDouble(double input) {
if (input == 0.0) {
return 0.0;
} else if ( input < 0.0) {
input = flipDouble(input);
input = sqrt(input);
return flipDouble(input);
}
return sqrt(input);
}
inline static double flipDouble(double input) {
return input * -1;
}
inline static double rangeInVec(std::vector<double> inputs) {
return maxInVec(inputs) - minInVec(inputs);
}
inline static double stdDevInVec(std::vector<double> inputs) {
if (inputs.size() < 2) {return 0.0;}
double mean = meanInVec(inputs);
double sq_sum = std::inner_product(inputs.begin(), inputs.end(), inputs.begin(), 0.0);
return std::sqrt(sq_sum / inputs.size() - mean * mean);
}
inline static double meanInVec(std::vector<double> inputs) {
double sum = std::accumulate(inputs.begin(), inputs.end(), 0.0);
return sum / inputs.size();
}
inline static double sumOfVec(std::vector<double> inputs) {
double total = 0.0;
for (unsigned int var = 0; var < inputs.size(); ++var) {
total += inputs[var];
}
return total;
}
inline static double maxInVec(std::vector<double> inputs) {
bool first = true;
double max;
for (unsigned int var = 0; var < inputs.size(); ++var) {
if (first) {
max = inputs[var];
first = false;
} else {
if (inputs[var] > max) {
max = inputs[var];
}
}
}
return max;
}
inline static double minInVec(std::vector<double> inputs) {
bool first = true;
double min;
for (unsigned int var = 0; var < inputs.size(); ++var) {
if (first) {
min = inputs[var];
first = false;
} else {
if (inputs[var] < min) {
min = inputs[var];
}
}
}
return min;
}
inline static std::vector<double> weightValueVector(std::vector<double> inputs,std::vector<double> weights) {
std::vector<double> results;
for (unsigned x = 0; x < inputs.size(); ++x) {
results.push_back(inputs[x] * weights[x]);
}
return results;
}
};
#endif /* MATHSFUNCTIONS_H_ */
答案 0 :(得分:1)
好吧,我发现了一些改进,
std :: vector应该通过const引用或引用传递。
您需要检查inputs.size()
部分功能。
提供weightValueVector
以将参考作为参数并在适当的位置修改其值会更有用,也更快。
答案 1 :(得分:1)
在已提供的答案之上:
在maxInVec
函数中:
- 零初始化double max
- 我建议size_t var
超过unsigned int var = 0
当您事先知道大小时,也可以使用reserve
作为向量,以避免在执行多个push_back
时重新分配内存
答案 2 :(得分:1)
也许速度和开发时间的最大收获是 使用现有的线性代数库而不是重新发明 方向盘,见
使用调整到您的计算机体系结构的BLAS和LAPACK。在 特别是,您的机器上可用的矢量指令和 缓存大小对性能有很大影响。
如果你的向量足够小,你可能会得到一个重要的 通过在堆栈上分配它们来获得性能提升。现在你是 在堆上分配它们。
使用template metaprogramming techniques可以消除 许多临时和不必要的循环在编译时。 To 在这里重复维基百科的例子:
假设您Vec x = alpha*(u -
v);
其中alpha
是标量而u
和v
是Vecs
。
如果你
以你正在做的方式实现它,它将花费你
至少2个临时向量(一个用于u-v
,一个用于。{
乘以alpha
)和 2通过内存
(2或3个循环:一个用于u-v
,一个用于alpha
如果未进行优化,则使用Vec x = alpha*(u -
v);
乘以及另外一个用于赋值。
如果您进行模板元编程,weightValueVector()
将归结为没有临时的单个循环和,这是您可以获得的最佳。表达式越复杂,增益就越大。
在 你没有这些操作的那一刻,但我想这只是一个问题 你需要它们的时间({{1}}是一个指示)。
当然,如果你使用线性代数库,你不必知道/担心任何这些,但你可以专注于你的应用程序,并获得超快的代码。