1

我写了一些数学函数在我的程序中使用,它们会被大量使用。我想提供代码,看看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_ */
4

3 回答 3

1

除了已经提供的答案之外:
maxInVec功能中:
-零初始化double max
-我建议您size_t var在事先知道大小时unsigned int var = 0
也可以将其用于向量,以避免在执行多个操作时重新分配内存reservepush_back

于 2013-10-12T00:44:00.117 回答
1
  1. 也许在速度和开发时间方面最大的收获是使用现有的线性代数库而不是重新发明轮子,请参阅

  2. 使用针对您的机器架构进行调整的BLASLAPACK 。特别是,机器上可用的向量指令和缓存大小对性能有很大的影响。

  3. 如果你的向量足够小,你可以通过在堆栈上分配它们来获得显着的性能提升。现在,您在堆上分配它们。

  4. 通过使用模板元编程技术,您可以在编译时消除许多临时循环和不必要的循环。在此处重复 Wikipedia 示例:

    假设你有 Vec x = alpha*(u - v);wherealpha是一个标量,u并且vVecs

    如果您以您正在执行的方式实现它,它将花费您至少 2 个临时向量(一个用于u-v和一个用于与 的乘法alpha2 个通过内存(2 或 3 个循环:一个用于u-v,一个用于乘法alpha如果它没有被优化掉 ,还有一个用于分配)。

    如果您进行模板元编程,Vec x = alpha*(u - v);将归结为一个没有临时循环的循环,这是您能得到的最好的。使用更复杂的表达式,增益变得更大。

    目前你没有这些操作,但我想你需要它们只是时间问题(weightValueVector()是一个迹象)。

当然,如果您使用线性代数库,您不必知道/担心任何这些,但您可以专注于您的应用程序并获得超快的代码。

于 2013-10-12T11:36:25.193 回答
1

嗯,我发现了一些改进,

  1. std::vector 应该通过 const 引用或引用传递。

  2. 您需要检查inputs.size()其中一些功能。

  3. weightValueVector提供将参考作为参数并在适当位置修改其值将是有用且更快的。

于 2013-10-11T23:34:19.960 回答