1

可以添加到 boost::accumulator 的值是否有限制?如果添加了大量条目,累加器是否会停止正常工作,或者内部算法是否足够强大以解释一组接近无穷大的值?

#include <iostream>
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics/stats.hpp>
#include <boost/accumulators/statistics/mean.hpp>
#include <boost/accumulators/statistics/moment.hpp>
using namespace boost::accumulators;

int main()
{
    // Define an accumulator set for calculating the mean and the
    // 2nd moment ...
    accumulator_set<double, stats<tag::mean, tag::moment<2> > > acc;

    // push in some data ...
    for (std::size_t i=0; i<VERY_LARGE_NUMBER; i++)
    {
      acc(i);
    }


    // Display the results ...
    std::cout << "Mean:   " << mean(acc) << std::endl;
    std::cout << "Moment: " << moment<2>(acc) << std::endl;

    return 0;
}
4

2 回答 2

1

如果您int是 32 位整数,则在计算时您将在 46341 * 46341 处得到有符号整数溢出,moment<2>因此您的程序具有未定义的行为。

为避免这种情况,i请转换为您在累加器中使用的类型:

acc(static_cast<double>(i));

现在,这将具有与正常相同的限制double。您可以添加任意数量的元素,只要您不超过内部力矩计算中的std::numeric_limits<double>::max()a 的限制 ( ) (对于超过限制的总和)。doublex2moment<2>

于 2021-01-08T14:52:52.277 回答
1

累加器统计考虑溢出,因此您需要仔细选择累加器类型。它不需要匹配您正在添加的对象的初始类型 - 您可以在累积时对其进行转换,然后获取统计信息并将其转换回原始类型。

您可以通过这个简单的示例看到它:

#include <bits/stdc++.h>
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics.hpp>

using namespace boost::accumulators;

int main(void) {
    accumulator_set<int8_t, features<tag::mean>> accInt8;
    accumulator_set<double, features<tag::mean>> accDouble;
    
    int8_t sum = 0; // range of int8_t: -128 to 127
    for (int8_t i = 1; i <= 100; i++) {
        sum += i; // this will overflow!
        accInt8(i); // this will also overflow
        accDouble((double)i);
    }
    
    std::cout << "sum from 1 to 100: " << (int)sum << " (overflow)\n";
    std::cout << "mean(<int8_t>): " << extract::mean(accInt8) << " (overflow)\n";
    std::cout << "mean(<double>): " << (int)extract::mean(accDouble) << "\n";
    
    return 0;
}

我使用int8_t了一个非常小的范围(-128 到 127)来证明如果你int8_t使用accumulator_set.

输出是:

sum from 1 to 100: -70 (overflow)
mean(<int8_t>): -7 (overflow)
mean(<double>): 50
于 2021-12-07T19:52:12.863 回答