添加到 boost::accumulator 的值的数量是否有限制?
Is there a limit on the number of values added to a boost::accumulator?
可以添加到 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;
}
如果您的 int
是一个 32 位整数,您将在计算 moment<2>
时在 46341 * 46341 处得到一个有符号整数溢出,因此您的程序具有未定义的行为。
为避免这种情况,将 i
转换为您在累加器中使用的类型:
acc(static_cast<double>(i));
这现在与普通 double
具有相同的限制。只要在内部力矩计算中不超过 double
的限制 (std::numeric_limits<double>::max()
) (x
2
对于 moment<2>
或超出限制的总和)。
累加器统计信息不 考虑溢出,因此您需要select 小心地选择累加器类型。它不需要匹配您正在添加的对象的初始类型——您可以在累加时对其进行转换,然后获取统计信息并将其转换回原始类型。
你可以这样看simple example:
#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;
}
我使用了范围很小(-128 到 127)的 int8_t
来证明如果使用 int8_t
从值 1 到 100(应该是 50)获取平均值会溢出作为 accumulator_set
.
的内部类型
输出为:
sum from 1 to 100: -70 (overflow)
mean(<int8_t>): -7 (overflow)
mean(<double>): 50
可以添加到 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;
}
如果您的 int
是一个 32 位整数,您将在计算 moment<2>
时在 46341 * 46341 处得到一个有符号整数溢出,因此您的程序具有未定义的行为。
为避免这种情况,将 i
转换为您在累加器中使用的类型:
acc(static_cast<double>(i));
这现在与普通 double
具有相同的限制。只要在内部力矩计算中不超过 double
的限制 (std::numeric_limits<double>::max()
) (x
2
对于 moment<2>
或超出限制的总和)。
累加器统计信息不 考虑溢出,因此您需要select 小心地选择累加器类型。它不需要匹配您正在添加的对象的初始类型——您可以在累加时对其进行转换,然后获取统计信息并将其转换回原始类型。
你可以这样看simple example:
#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;
}
我使用了范围很小(-128 到 127)的 int8_t
来证明如果使用 int8_t
从值 1 到 100(应该是 50)获取平均值会溢出作为 accumulator_set
.
输出为:
sum from 1 to 100: -70 (overflow)
mean(<int8_t>): -7 (overflow)
mean(<double>): 50