C++ 无损耗地跟踪向量元素的总和

C++ 无损耗地跟踪向量元素的总和,c++,precision,C++,Precision,我有一段代码在一个程序中运行数百万次,因此它对性能至关重要。在这个函数中发生的一件事是向量V中单个元素的更新,我需要跟踪它元素的和S。通过在创建向量时计算元素和一次,然后删除更新元素的当前值,然后对新值求和(如中所示),我获得了极大的性能提升 S -= V[i]; S += newValue; V[i] = newValue; 而不是用std::acculate(V.begin(),V.end(),0.0)来重新计算整个总和。在程序的另一部分中,我使用S和作为可能结果的范围生成一个值,然后发现

我有一段代码在一个程序中运行数百万次,因此它对性能至关重要。在这个函数中发生的一件事是向量V中单个元素的更新,我需要跟踪它元素的和S。通过在创建向量时计算元素和一次,然后删除更新元素的当前值,然后对新值求和(如中所示),我获得了极大的性能提升

S -= V[i];
S += newValue;
V[i] = newValue;
而不是用std::acculate(V.begin(),V.end(),0.0)来重新计算整个总和。在程序的另一部分中,我使用S和作为可能结果的范围生成一个值,然后发现生成的值超出范围。那么我的问题是:以这种方式存储元素之和是否会降低精度?另一种说法是:在充分实现这个更新过程之后,S的值是否会偏离“累计”返回的值?我现在正在测试这个假设,但是如果有人对机器操作有更好的了解,我会非常感激。如果确实存在精度损失并导致错误,是否有一种快速但更精确的方法来存储总和S

编辑:存储在V中的数据类型为double:
std::vector V
及其元素之和也存储在双变量S中:
double S

Edit2:根据要求,以下是我对求和过程的更详细的看法:

    #include <random>
    #include <vector>
    #include <iostream>

    int chooseUpdateIndex(
    // here we choosen some element of V to be updated. The probability
    // of choosing index 'i' is just 'V[i]/S'
        std::uniform_real_distribution<double>& uniform,
        std::default_random_engine& rng,
        double S,
        std::vector<double>& V)
    {
        double randomLength = uniform(rng)*S;
        double partialSum = 0;
        for (int i = 0; i < V.size(); ++i) {
            partialSum += V[i];
            if (randomLength < partialSum) return i;
        }
        throw std::runtime_error("reached end of function without selecting an index");
    }

    int main()
    {
        std::default_random_engine rng;
        std::uniform_real_distribution<double> uniform(0.0, 1.0);
        std::vector<double> V(200);

        for (auto& v : V) v = 10*uniform(rng); // populate vector
        double S = std::accumulate(V.begin(), V.end(), 0.0); // make initial sum
        for (int i = 0; i < 1000000; ++i) {
            // sometimes, with enough iterations, this function call throws an error
            // because the randomLength is greater than the length of vector V
            int updateIndex = chooseUpdateIndex(uniform, rng, S, V);
            double newValue = uniform(rng)*10;
            S -= V[updateIndex];
            S += newValue;
            V[updateIndex] = newValue;
        }

        double recalculatedS = std::accumulate(V.begin(), V.end(), 0.0);

        if (S == recalculatedS) std::cout << "S == recalculatedS\n";
        else if (S < recalculatedS) std::cout << "S < recalculatedS\n";
        else std::cout << "S > recalculatedS\n";

        return 0;
    }
#包括
#包括
#包括
int chooseUpdateIndex(
//这里我们选择了V的一些元素进行更新
//选择索引'i'的方法只是'V[i]/S'
标准::均匀实分布和均匀分布,
标准::默认随机引擎和rng,
双S,
标准::向量和向量(V)
{
双随机长度=均匀(rng)*S;
双侧额=0;
对于(int i=0;i如果(S==重新计算)std::cout如果数字有小数,我希望随着时间的推移会出现精度损失。对于整数,您主要需要担心溢出。您的回答非常模糊。请在您的问题中添加一个。我认为不需要更多的代码。问题只需要指定
V
中元素的类型和预期的最小值最大值是<代码> s>代码>。这取决于总和是否在S和向量项都可以包含的范围内。请考虑Kahan-Manges算法来跟踪运行错误。