Die Boost C++ Bibliotheken

Kapitel 58. Boost.Accumulators

Boost.Accumulators bietet Klassen an, die Proben oder Messwerte verarbeiten können. So kann zum Beispiel der größte oder kleinste Wert gefunden oder die Summe aller Werte gebildet werden. Während dies auch mit Algorithmen aus der Standardbibliothek möglich ist, unterstützt Boost.Accumulators zahlreiche Berechnungen aus der Statistik. So kann zum Beispiel der Mittelwert oder die Standardabweichung berechnet werden.

Die Bibliothek heißt Boost.Accumulators, weil ein wesentliches Konzept der Akkumulator ist. Ein Akkumulator ist vergleichbar mit einem Container, der Ergebnisse neu berechnet, wenn Sie einen neuen Wert übergeben. Der Wert wird nicht zwangsläufig im Akkumulator gespeichert. Stattdessen berechnet der Akkumulator Zwischenergebnisse ständig neu, wenn Sie ihn mit Werten füttern.

Die Bibliothek Boost.Accumulators besteht aus drei Teilen:

Alle von Boost.Accumulators angebotenen Klassen und Funktionen befinden sich in boost::accumulators oder darunter liegenden Namensräumen. So sind zum Beispiel alle Akkumulatoren im Namensraum boost::accumulators::tag definiert.

Beispiel 58.1. Zählen mit boost::accumulators::tag::count
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics.hpp>
#include <iostream>

using namespace boost::accumulators;

int main()
{
  accumulator_set<int, features<tag::count>> acc;
  acc(4);
  acc(-6);
  acc(9);
  std::cout << count(acc) << '\n';
}

Im Beispiel 58.1 kommt mit boost::accumulators::tag::count ein einfacher Akkumulator zum Einsatz: Er zählt die Werte, die dem Akkumulator übergeben werden. So gibt das Beispielprogramm 3 aus, wenn Sie es ausführen.

Wenn Sie einen Akkumulator verwenden möchten, greifen Sie auf die Klasse boost::accumulators::accumulator_set zu. Bei dieser Klasse handelt es sich um ein Template, dem Sie als ersten Parameter den Typ übergeben, den Sie für die Werte verwenden möchten, die verrechnet werden sollen. Im Beispiel 58.1 ist dies int.

Als zweiten Parameter geben Sie die Akkumulatoren an, die Sie verwenden möchten. Beachten Sie, dass Sie mehrere Akkumulatoren verwenden können. Der Name der Klasse boost::accumulators::accumulator_set deutet es an, dass beliebig viele Akkumulatoren verwaltet werden können.

Genau genommen geben Sie keine Akkumulatoren an, sondern Features. Mit Features legen Sie fest, was berechnet werden soll. Sie bestimmen das Was, nicht das Wie. So kann es für Features unterschiedliche Implementationen geben. Bei diesen Implementationen handelt es sich um Akkumulatoren.

Im Beispiel 58.1 wird mit boost::accumulators::tag::count angegeben, dass ein Akkumulator verwendet werden soll, der Werte zählt. Existieren mehrere Akkumulatoren, die Werte zählen können, wählt Boost.Accumulators einen Standardakkumulator aus.

Beachten Sie, dass Sie Features nicht direkt als zweiten Parameter an boost::accumulators::accumulator_set übergeben, sondern über boost::accumulators::features.

Wenn Sie ein Objekt vom Typ boost::accumulators::accumulator_set erstellt haben, können Sie es wie eine Funktion verwenden und über den Operator operator() Werte übergeben. Diese werden sofort von dem oder den verwendeten Akkumulatoren verrechnet. Die Werte, die Sie übergeben, müssen zu dem Typ passen, den Sie als ersten Parameter an boost::accumulators::accumulator_set übergeben haben.

Für jedes Feature existiert ein gleichnamiger Extractor. Es handelt sich dabei um eine Funktion, die Sie aufrufen können, um das aktuelle Ergebnis eines Akkumulators zu erhalten. Im Beispiel 58.1 wird der Extractor boost::accumulators::count() aufgerufen und ihm als einziger Parameter acc übergeben. boost::accumulators::count() gibt daraufhin 3 zurück.

Beispiel 58.2. Durchschnitt und Varianz mit mean und variance errechnen
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics.hpp>
#include <iostream>

using namespace boost::accumulators;

int main()
{
  accumulator_set<double, features<tag::mean, tag::variance>> acc;
  acc(8);
  acc(9);
  acc(10);
  acc(11);
  acc(12);
  std::cout << mean(acc) << '\n';
  std::cout << variance(acc) << '\n';
}

Im Beispiel 58.2 werden die beiden Features boost::accumulators::tag::mean und boost::accumulators::tag::variance eingesetzt, um Durchschnitt und Varianz für fünf Werte zu errechnen. Wenn Sie das Beispielprogramm ausführen, wird 10 und 2 ausgegeben.

Die Varianz von 2 kommt zustande, weil Boost.Accumulators für jeden der fünf Werte ein Gewicht von 0,2 annimmt. Der mit boost::accumulators::tag::variance ausgewählte Akkumulator gehört zu denjenigen, die mit Gewichten arbeiten. Wird kein Gewicht explizit angegeben, erhält jeder Wert automatisch das gleiche Gewicht.

Beispiel 58.3. Gewichtete Varianz errechnen
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics.hpp>
#include <iostream>

using namespace boost::accumulators;

int main()
{
  accumulator_set<double, features<tag::mean, tag::variance>, int> acc;
  acc(8, weight = 1);
  acc(9, weight = 1);
  acc(10, weight = 4);
  acc(11, weight = 1);
  acc(12, weight = 1);
  std::cout << mean(acc) << '\n';
  std::cout << variance(acc) << '\n';
}

Im Beispiel 58.3 wird mit int ein dritter Template-Parameter an boost::accumulators::accumulator_set übergeben. Dieser Parameter beschreibt den Typ der Gewichte. So kann in diesem Beispiel jeder Wert mit einer Ganzzahl gewichtet werden.

Boost.Accumulators verwendet Boost.Parameter, um zusätzliche Angaben wie Gewichte als Name/Wert-Paare zu übergeben. Der Parameter für Gewichte heißt weight. Sie können den Parameter wie eine Variable behandeln und ihm einen Wert zuweisen. Das Name/Wert-Paar wird als zusätzlicher Parameter hinter jedem Wert an den Akkumulator übergeben.

Im Beispiel hat der Wert 10 ein Gewicht von 4, während alle anderen Werte ein Gewicht von 1 haben. Der Durchschnitt ist unverändert 10, da Gewichte für die Berechnung des Durchschnitts keine Rolle spielen. Die Varianz ist nun jedoch 1,25. Sie hat sich im Vergleich zum vorherigen Beispiel verringert, da der mittlere Wert stärker gewichtet ist als die anderen.

Boost.Accumulators bietet zahlreiche weitere Akkumulatoren an. Diese werden ähnlich wie die oben vorgestellten Akkumulatoren verwendet. Die Dokumentation der Bibliothek enthält eine Referenz, um einen Überblick über die verfügbaren Akkumulatoren zu erhalten.