簡體   English   中英

添加到 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 位 integer,則在計算moment<2>時,您將在 46341 * 46341 處獲得簽名的 integer 溢出,因此您的程序具有未定義的行為。

為避免這種情況,請將i轉換為您在累加器中使用的類型:

acc(static_cast<double>(i));

這現在將具有與普通double相同的限制。 您可以根據需要添加任意數量的元素,只要不超過內部矩計算中的double的限制( std::numeric_limits<double>::max() )( x 2moment<2>或超過限制的總和)。

累加器統計考慮溢出,因此需要仔細檢查累加器類型 select。 它不需要匹配您正在添加的對象的初始類型——您可以在累積時對其進行轉換,然后獲取統計信息並將其轉換回原始類型。

您可以通過這個簡單的示例看到它:

#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的內部類型,從值 1 到 100(應該是 50)獲取平均值會溢出。

output 是:

sum from 1 to 100: -70 (overflow)
mean(<int8_t>): -7 (overflow)
mean(<double>): 50

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM