#include #include #include #include #include #include #include #include using namespace std; class PDF { public: virtual double getMean() const = 0; virtual ~PDF() = default; }; class NormV : public PDF { public: double mean, stddev; NormV (double mean_ = 0, double stddev_ = 1) : mean(mean_), stddev(stddev_) {} virtual double operator()(double x) const { return M_2_SQRTPI / (2 * M_SQRT2 * stddev) * exp(-((x - mean) * (x - mean)) / (2*stddev*stddev)); } double getMean() const { return mean; } }; class GleichV : public PDF { private: double from, to; public: GleichV(double from_, double to_): from(from_), to(to_) { if (to <= from) { ostringstream sstr; sstr << "NormV(" << from << ", " << to << ")"; throw invalid_argument(sstr.str()); } } virtual double operator()(double x) const { if (x < from || x > to) return 0; return 1 / (to - from); } double getMean() const { return from + (to - from) / 2; } }; class ExpV : public PDF { public: double rate; ExpV(double rate_): rate(rate_) {} virtual double operator()(double x) const { if (x < 0) return 0; return rate * exp(- rate * x); } double getMean() const { return 1 / rate; } }; class SumV : public PDF { private: list> pdfs; public: explicit SumV(PDF* pdf) { *this += pdf; } SumV(const SumV&) = delete; SumV& operator+=(PDF* pdf) { pdfs.push_back(unique_ptr{pdf}); return *this; } double getMean() const { double sum = 0; for (const unique_ptr& pdf: pdfs) sum += pdf->getMean(); return sum; } }; const map> pdfs{ {"norm", []() -> PDF* { double mean, stddev; cout << "mean, stddev = "; cin >> mean >> stddev; return new NormV{mean, stddev}; } }, {"gleich", []() -> PDF* { double from, to; cout << "from, to = "; cin >> from >> to; return new GleichV{from, to}; } }, {"exp", []() -> PDF* { double rate; cout << "rate = "; cin >> rate; return new ExpV{rate}; } } }; int main() { unique_ptr sum; while (true) { string fun; cout << "sum += "; if (!(cin >> fun)) { cout << endl; break; } try { PDF* pdf = (pdfs.at(fun))(); if (sum) *sum += pdf; else sum = unique_ptr{new SumV{pdf}}; } catch (const out_of_range&) { cout << "Unknown distribution: " << fun << endl; } } cout << "sum.getMean() = " << sum->getMean() << endl; }