如何将多个集成顺序集成到我的Integrator类中?

问题描述 投票:1回答:1

我有一个有效的Integrator类,它将计算单个变量的基本函数的确定积分。我已经测试了一些基本功能的集成,并且看来工作正常。

我现在想扩展此类,以便能够执行相同功能的多个积分……这就是我遇到的障碍...


这是我的集成器类和一些基本用法示例:

Integrator.h

#pragma once

#include <algorithm>
#include <utility>
#include <functional>

struct Limits {
    double lower;
    double upper;

    Limits() : lower{ 0 }, upper{ 0 } {}
    Limits(double a, double b) : lower{ a }, upper{ b } {
        if (a > b) std::swap(lower, upper);
    }

    void applyLimits(double a, double b) {
        lower = a;
        upper = b;
        if (a > b) std::swap(lower, upper);
    }
};

class Integrator {
private:
    Limits limits_;
    std::function<double(double)> integrand_;

    double dx_;
    double dy_;  
    double integral_; 
    int step_size_;

public:
    Integrator(Limits limits, int stepSize, std::function<double(double)> integrand, double dy = 0) 
        : limits_{ limits }, 
        step_size_{ stepSize }, 
        integrand_{ integrand }, 
        dx_{ 0 }, dy_{ 0 } 
    {}
    ~Integrator() = default;

    constexpr double dx() const { return this->dx_; }
    constexpr double dy() const { return this->dy_; }
    constexpr double integral() const { return this->integral_; }

    Limits limits() const { return limits_; }    
    std::function<double(double)>* integrand() { return &this->integrand_; }

    // This is always a 1st order of integration!
    constexpr double evaluate() {
        double distance = limits_.upper - limits_.lower;      // Distance is defined as X0 to XN. (upperLimit - lowerLimit) 
        dx_ = distance / step_size_;                          // Calculate the amount of iterations by dividing 
                                                              // the x-distance by the dx stepsize
        integral_ = 0;                                        // Initialize area to zero
        for (auto i = 0; i < step_size_; i++) {               // For each dx step or iteration calculate the area at Xi
            dy_ = integrand_(limits_.lower + i * dx_);
            double area = dy_ * dx_;                          // Where the width along x is defines as dxStepSize*i 
            integral_ += area;                                // and height(dy) is f(x) at Xi. Sum all of the results
        }

        return integral_;
    }
};

main.cpp

#include <iostream>
#include <exception>
#include <cmath>

#include "Integrator.h"

constexpr double PI = 3.14159265358979;

constexpr double funcA(double x) {
    return x;
}

constexpr double funcB(double x) {
    return (x*x);
}

constexpr double funcC(double x) {
    return ((0.5*(x*x)) + (3*x) - (1/x));
}

double funcD(double x) {
    return sin(x);
}

int main() {
    try {    
        std::cout << "Integration of f(x) = x from a=3.0 to b=5.0\nwith an expected output of 8\n";
        Integrator integratorA(Limits(3.0, 5.0), 10000, &funcA);
        std::cout << integratorA.evaluate() << '\n';        

        std::cout << "\n\nIntegration of f(x) = x^2 from a=2.0 to b=20.0\nwith an expected output of 2664\n";
        Integrator integratorB(Limits(2.0, 20.0), 10000, &funcB);
        std::cout << integratorB.evaluate() << '\n';

        std::cout << "\n\nIntegration of f(x) = (1\\2)x^2 + 3x - (1\\x) from a=1.0 to b=10.0\nwith an expected output of 312.6974\n";
        Integrator integratorC(Limits(1.0, 10.0), 10000, &funcC);
        std::cout << integratorC.evaluate() << '\n';

        std::cout << "\n\nIntegration of f(x) = sin(x) from a=0.0 to b=" <<PI<< "\nwith an expected output of 2\n";
        Integrator integratorD(Limits(0.0, PI), 10000, &funcD);
        std::cout << integratorD.evaluate() << '\n';

    } catch (const std::exception& e) {
        std::cerr << e.what() << std::endl;
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

输出

Integration of f(x) = x from a=3.0 to b=5.0
with an expected output of 8
7.9998


Integration of f(x) = x^2 from a=2.0 to b=20.0
with an expected output of 2664
2663.64


Integration of f(x) = (1\2)x^2 + 3x - (1\x) from a=1.0 to b=10.0
with an expected output of 312.6974
312.663


Integration of f(x) = sin(x) from a=0.0 to b=3.14159
with an expected output of 2
2

我正在考虑向该类添加类似于其evaluate()函数的另一个函数...目前看起来像这样:

double integrate(Limits limits, double dy) {
    double total = 0;
    dy_ = dy;

    for (int i = 0; i < step_size_; i++) {
        double yi = limits_.lower*i*dy_;
        double dx = static_cast<double>(yi - limits.lower) / stepSize;
        double innerArea = 0;

        for (int j = 0; j < step_size_; j++) {
            Integrator inner(limits, step_size_, integrand_, dy_);
            innerArea += inner.evaluate();
        }
        double outerArea = innerArea * dy_;
        total += outerArea;
    }

    integral_ = total;
    return integral_;
}

这就是我感到困惑或困惑的地方。当涉及到内部和外部积分的积分极限时,我不确定如何正确实现此功能。

例如,下面的整数:

double integration

内部积分的上限基于每次计算迭代的y,这必须动态完成。从[3,5][1,y],外部积分是笔直的。

我认为我走在正确的轨道上,但是上述方法中的某些方法完全不可用...我从预期或预期值中得到了完全错误的值...

非常欢迎任何建议和技巧!


编辑-注意-我在上面提供了错误的图像,该图像已更新...

期望的输出应该是:65.582,带有正确提供的功能f(x) = 1/2x^2 + 3x - (1/x)。当我尝试计算双积分时,我最终得到了这个...

这是添加到驱动程序或main.cpp ...]中的代码>

std::cout << "\n\nTesting Double Integration of f(x) = (1\\2)x^2 + 3x - (1\\x) from [3,5] and [1,y]\nwith an expected output of 65.582\n";
Integrator integratorE(Limits(3, 5), 1000, &funcC);
double dy = integratorE.limits().upper - integratorE.limits().lower;
integratorE.integrate(Limits(1, integratorE.integral()), dy);
std::cout << integratorE.integral() << '\n';

但是,它没有在控制台上打印任何内容...


编辑

我没有得到足够的输出,因为我没有等待足够长的时间。迭代由step_size定义为1000。最终将生成1000^1000个总迭代...在构建Integrator对象时,我已经忽略了这一点。我已经在代码中将此值更改为step_size为100。现在我的应用程序正在输出2.68306e+189的值,这显然是错误的!当我将step_size增大到500时,它给了我大约6.62804e+190的顺序,但这仍然是错误的。

我有一个有效的Integrator类,它将计算单个变量的基本函数的确定积分。我已经测试了一些基本功能的集成,并且似乎可以正常使用...

c++ algorithm c++17 numerical-integration
1个回答
0
投票

返回并再次观看视频后,我开始分解类的integrate()函数中的双循环结构。

© www.soinside.com 2019 - 2024. All rights reserved.