【Matlab】复化梯形公式求积分、求二重积分

博客主要介绍了利用复化梯形公式求积分和二重积分。包括求积分I(f)=∫15xsinxdx的近似值,精确至7位有效数字;还给出求二重积分的通用程序,采用逐次二分步长和外推思想,计算至相邻两次近似值之差绝对值不超给定精度,如计算I(f)=∫0π/6(∫0π/3tan(x2+y2)dx)dy。

一、复化梯形公式求积分

1.1 题目

利用复化梯形公式计算
I ( f ) = ∫ 1 5 s i n x x d x I(f) = \int_1^5{\frac{sinx}{x}dx} I(f)=15xsinxdx
的近似值,精确至7位有效数字。

1.2 程序

clc; clear all
syms x 

%% 已知条件
Fx(x) = sin(x)/x;
a = 1;
b = 5;
epsilon = 5e-8;
e = 1;
T = []; % 存放Tf的值
h = b-a;
Xk1 = [a, b];  % 存放已选的 xk
Xk2 = [];      % 存放将要使用的 x(k+1/2)
sumfx = 0;     % sum( fx(k+1/2) )

%% 计算
digits(8)
format long
k = 0;
Tf = vpa( b - a ) / 2 * ( Fx(a) + Fx(b) );
T = [T, Tf];
fprintf('k=%d, 2^k=%d, Tk=%0.8f\n',k,2^k,Tf) 

while(e>epsilon)
    for i=1:length(Xk1)-1
        temp = ( Xk1(i) + Xk1(i+1) ) / 2;
        sumfx = sumfx + Fx(temp);
        Xk2 = [Xk2,temp];
    end
    Xk1 = [Xk1,Xk2];
    Xk1 = sort(Xk1);
    
    k = k + 1;
    Tf = vpa( 0.5 * ( Tf + h * sumfx ) );
    T = [T, Tf];
    e = abs(Tf - T(end-1))/3;
    fprintf('k=%d, 2^k=%d, Tk=%0.8f, e=%0.8f\n',k,2^k,Tf,e) 
    
    % 更新值
    h = h / 2;
    sumfx = 0;
    Xk2 = [];
end

If = Tf;
fprintf('复化梯形求积公式的结果为:%0.8f\n',If)

1.3 运行结果

在这里插入图片描述

二、复化梯形公式求二重积分

2.1 题目

(1)给定积分 I ( f ) = ∫ c d ( ∫ a b f ( x , y ) d x ) d y I(f)=\int_{c}^{d}\left(\int_{a}^{b} f(x, y) \mathrm{d} x\right) \mathrm{d} y I(f)=cd(abf(x,y)dx)dy,取初始步长 h h h k k k及精度 ε \varepsilon ε,应用复化梯形公式,采用逐次二分步长的方法并应用外推思想编制计算 I ( f ) I(f) I(f)的通用程序,计算至相邻两次近视值之差的绝对值不超过 ε \varepsilon ε为止;

(2)用所编程序计算积分 I ( f ) = ∫ 0 π / 6 ( ∫ 0 π / 3 tan ⁡ ( x 2 + y 2 ) d x ) d y I(f)=\int_{0}^{\pi / 6}\left(\int_{0}^{\pi / 3} \tan \left(x^{2}+y^{2}\right) \mathrm{d} x\right) \mathrm{d} y I(f)=0π/6(0π/3tan(x2+y2)dx)dy
ε = 1 2 × 1 0 − 5 \varepsilon=\frac{1}{2} \times 10^{-5} ε=21×105

2.2 程序

2.2.1 二重积分通用程序

function[result] = trapezoid(a,b,c,d,F,epsilon)
    %% 初值条件
    T0 = [];  % 存放Tm,n(f)
    T1 = [];  % 存放T(1)m,n(f)
    T2 = [];  % 存放T(2)m,n(f)
    T3 = [];  % 存放T(3)m,n(f)

    m = 1;  % 将[a,b] m等分
    n = 1;  % 将[c,d] n等分; 注:虽然这里m与n相等,但分开计算。
    h = (b - a) / m;  % x的步长
    k = (d - c) / n;  % y的步长
    xx = [a,b];
    yy = [c,d];
    e = 1; % 误差

    %% 计数位
    count = 0;
    T0_count = 0;
    T1_count = 0;
    T2_count = 0;
    T3_count = 0;

    %% 计算
    digits(10)
    T =  h * k  / 4 * ( F(xx(1),yy(1)) + F(xx(1),yy(2)) + F(xx(2),yy(1)) + F(xx(2),yy(2)) )   ;
    T0 = [T0, T];
    T0_count = T0_count + 1;
    count = 1;
    fprintf('k=%d, 2^k=%d, T0=%0.8f\n',count,2^count,T) 

    while(e>epsilon)
        m = 2 * m;
        n = 2 * n;
        h = (b - a) / m;
        k = (d - c) / n;

        % 计算x、y的取值
        xx = [a];  % 暂时只存入左边值
        yy = [c];  % 暂时只存入左边值
        for i = 1:m
            temp = a + i * h;
            xx = [xx,temp];
        end
        for j = 1:n
            temp = c + j * k;
            yy = [yy,temp];
        end

        % 计算T0
        T = 0;
        for i = 1:m
            for j = 1:n
                T = T + vpa( h * k /4 * (F(xx(i),yy(j)) + F(xx(i),yy(j+1)) + F(xx(i+1),yy(j)) + F(xx(i+1),yy(j+1)) ) );
            end
        end
        T0 = [T0,T];
        T0_count = T0_count + 1;
        count = count + 1;
        fprintf('k=%d, 2^k=%d, T0=%0.8f',count,2^count,T) 

        % 计算T1
        if T0_count - T1_count == 2 && T0_count >= 2
            temp = 4 / 3 * T0(end) - 1 / 3 * T0(end-1);
            T1 = [T1,temp];
            T1_count = T1_count + 1;
            fprintf(', T1=%0.8f',T1(end)) 
        end

        % 计算T2
        if T1_count - T2_count == 2  && T1_count >= 2
            temp = 4 / 3 * T1(end) - 1 / 3 * T1(end-1);
            T2 = [T2,temp];
            T2_count = T2_count + 1;
            fprintf(', T2=%0.8f',T2(end)) 
        end

        % 计算T3
        if T2_count - T3_count == 2  && T2_count >= 2
            temp = 4 / 3 * T2(end) - 1 / 3 * T2(end-1);
            T3 = [T3,temp];
            T3_count = T3_count + 1;
            fprintf(', T3=%0.8f',T3(end)) 
        end

        if T3_count >= 2
            e = T3(end) - T3(end-1);
            fprintf(', e=%0.8f',e) 
        end
        fprintf('\n') 
    end
    fprintf('复化梯形二重积分求积公式的结果为:%0.8f\n',T3(end))
    result = T3(end);
end

2.2.2 主函数程序

clc; clear;

syms x y
F(x,y) = tan(x^2 + y^2);
a = 0;
b = pi/3;
c = 0;
d = pi/6;
epsilon = 0.5e-5;

result = trapezoid(a,b,c,d,F,epsilon);

2.3 运行结果

在这里插入图片描述

<think>根据用户需,我们需要实现辛普森公式MATLAB代码。辛普森公式是将积分区间分割成若干子区间,在每个子区间上应用辛普森公式,然后和。 辛普森公式的基本思想: 将区间$[a,b]$等分为$n$个子区间($n$为偶数),每个子区间长度为$h=(b-a)/n$,节点为$x_i=a+ih$,$i=0,1,\dots,n$。则辛普森公式为: $$ \int_a^b f(x) dx \approx \frac{h}{3} \left[ f(a) + f(b) + 4 \sum_{i=1}^{n/2} f(x_{2i-1}) + 2 \sum_{i=1}^{n/2-1} f(x_{2i}) \right] $$ 注意:辛普森公式区间分割数$n$为偶数。 我们将编写一个MATLAB函数,输入参数为积分下限$a$,上限$b$,分割的子区间数$n$(偶数),以及被积函数$f$。输出为积分的近似值。 函数定义: ```matlab function S = comp_simpson_integral(a, b, n, f) % 辛普森公式积分 % 输入: a - 积分下限 % b - 积分上限 % n - 分割的子区间数(偶数) % f - 被积函数,函数句柄 % 输出: S - 积分近似值 h = (b - a) / n; % 步长 x = a:h:b; % 节点数组 % 计算端点函数值 fa = f(a); fb = f(b); % 计算奇数节点(从x1到x_{n-1},注意下标从1开始)和偶数节点(从x2到x_{n-2})的函数值 sum_odd = 0; % 奇数项和 sum_even = 0; % 偶数项和 % 注意:节点数组x的长度为n+1,下标从1到n+1 % 奇数节点:下标为2,4,...,n(即x1,x3,...,x_{n-1})? 这里需要仔细分析 % 实际上,在辛普森公式中,奇数节点对应的是每个子区间的中点,但这里我们划分的节点包括所有整数节点。 % 按照公式,我们需要将节点分为奇数索引和偶数索引(从0开始计数,但在MATLAB中下标从1开始) % 因此,在区间[a,b]上,节点为x0,x1,...,xn。其中x0=a, xn=b。 % 公式:奇数节点(即下标为奇数的节点,如x1,x3,...,x_{n-1})和偶数节点(下标为偶数的节点,如x2,x4,...,x_{n-2}) % 在MATLAB中,节点数组x(1)=a, x(2)=a+h, x(3)=a+2h, ... , x(n+1)=b % 因此,奇数节点(即i为奇数)对应的数组下标为:2,4,...,n(即从第2个节点开始,每隔一个取一个,直到第n个节点)? % 注意:公式中的奇数节点实际上是指每个子区间的中点,但辛普森公式也可以写成上述节点形式。 % 正确的做法: % 对于下标i(从0开始): % 偶数下标:i=0,2,4,...,n 对应MATLAB中的索引:1,3,5,...,n+1 % 奇数下标:i=1,3,5,...,n-1 对应MATLAB中的索引:2,4,6,...,n % 但注意,在公式中,端点a和b已经单独处理,中间节点分为奇数下标和偶数下标。 % 公式中:4倍的是奇数下标节点(不包括端点),2倍的是偶数下标节点(不包括端点)。 % 因此,我们计算: % 奇数下标节点:从i=1到i=n-1(步长为2),即MATLAB索引为2:2:n % 偶数下标节点:从i=2到i=n-2(步长为2),即MATLAB索引为3:2:n-1 % 注意:当n>=2时,我们才能这样计算。 % 计算奇数节点(即下标为奇数的点,在MATLAB中对应索引为2,4,...,n)的函数值之和 for i = 1:n/2 % 奇数节点:x_{2i-1},在MATLAB中对应索引为2*i-1+1? 重新考虑: % 节点:x0=a (索引1), x1=a+h (索引2), x2=a+2h (索引3), ..., xn=b (索引n+1) % 我们需要的是奇数下标的节点(下标1,3,...,n-1)? 不对,公式中要的是: % 4倍的是区间中点,即每个子区间的中点,在节点划分中,这些中点实际上就是下标为奇数的节点(从1到n-1)? % 实际上,辛普森公式的节点表示中,奇数节点对应的是每个子区间的中点,但这里我们划分的节点包括所有整数节点,所以每个子区间中点是两个整数节点的中点?不对,我们划分的节点就是整数节点,而每个子区间是相邻两个节点构成的区间,所以每个子区间中点并不在节点上。但辛普森公式的另一种写法是直接用整数节点表示,不需要额外计算中点。 % 重新审视辛普森公式的标准写法: % 将区间[a,b]分成n个相等的小区间(n为偶数),每个小区间长度为h,节点为x_i = a+i*h, i=0,...,n % 则积分近似为: % S = h/3 * [f(x0) + f(xn) + 4*(f(x1)+f(x3)+...+f(x_{n-1})) + 2*(f(x2)+f(x4)+...+f(x_{n-2}))] % 其中,奇数节点(下标为奇数的节点,即i为奇数)乘以4,偶数节点(下标为偶数,且不包括端点)乘以2。 % 因此,在MATLAB中: % 奇数节点:i=1,3,...,n-1 对应索引为2,4,...,n % 偶数节点:i=2,4,...,n-2 对应索引为3,5,...,n-1 % 计算奇数节点(索引2,4,...,n)的函数值之和 sum_odd = sum(f(x(2:2:n))); % 注意:x(2:2:n)表示从第2个元素开始,每隔一个取一个,直到第n个元素(因为n是偶数,所以最后一个元素是第n个,对应节点x_{n-1}?不对,索引2对应x1,索引n对应x_{n-1}? 因为节点总数为n+1,所以索引n对应的是x_{n-1},而索引n+1对应x_n=b。但这里我们的x(2:2:n)取的是索引为2,4,...,n的元素,这些元素对应的节点是x1,x3,...,x_{n-1}(因为索引2对应i=1,索引4对应i=3,索引n对应i=n-1,因为n是偶数,所以n-1是奇数)。所以正确。 % 计算偶数节点(索引3,5,...,n-1)的函数值之和 if n>=4 sum_even = sum(f(x(3:2:n-1))); % 索引3,5,...,n-1,对应节点x2,x4,...,x_{n-2} else sum_even = 0; % 当n=2时,没有偶数节点(因为只有两个区间,节点为x0,x1,x2,其中x0和x2是端点,x1是奇数节点,没有偶数节点) end % 应用公式 S = (h/3) * (fa + fb + 4*sum_odd + 2*sum_even); end ``` 但是,上面的代码中,我们使用了向量操作,可以避免循环。我们可以直接使用数组索引和sum函数。因此,我们可以简代码: ```matlab function S = comp_simpson_integral(a, b, n, f) % 辛普森公式积分 % 输入: a - 积分下限 % b - 积分上限 % n - 分割的子区间数(偶数) % f - 被积函数,函数句柄 % 输出: S - 积分近似值 if mod(n,2) ~= 0 error('n必须为偶数'); end h = (b - a) / n; x = a:h:b; % 所有节点 % 端点函数值 fa = f(a); fb = f(b); % 奇数节点:从x1到x_{n-1},步长2(即索引2,4,...,n) % 注意:x(1)是a,x(2)是x1,x(3)是x2,...,x(n+1)是b % 所以奇数节点索引:2,4,...,n odd_idx = 2:2:n; % 注意:这些索引对应的节点是x1,x3,...,x_{n-1}(因为索引2对应第一个节点x1,索引n对应节点x_{n-1}) % 偶数节点:从x2到x_{n-2},步长2(即索引3,5,...,n-1) even_idx = 3:2:n-1; % 节点x2,x4,...,x_{n-2} % 计算函数值 y = f(x); % 整个节点数组的函数值 sum_odd = sum(y(odd_idx)); sum_even = sum(y(even_idx)); S = (h/3) * (fa + fb + 4*sum_odd + 2*sum_even); end ``` 测试例子:计算$\int_0^1 \frac{4}{1+x^2} dx$,其精确值为$\pi$。 测试代码: ```matlab f = @(x) 4./(1+x.^2); a = 0; b = 1; n = 10; % 取10个子区间(偶数) S = comp_simpson_integral(a, b, n, f); disp(['辛普森积分近似值: ', num2str(S)]); disp(['精确值: ', num2str(pi)]); disp(['误差: ', num2str(abs(S-pi))]); ``` 用户也可以参考引用[2]中的方法,将辛普森公式梯形公式进行比较。 注意:辛普森公式的精度通常比梯形公式高,且收敛速度更快。 相关问题: 1. 辛普森公式的误差估计是什么? 2. 为什么辛普森公式区间分割数n为偶数? 3. 如何用辛普森公式计算二重积分? 4. 辛普森公式与龙贝格积分方法有何联系?</think>### MATLAB 辛普森积分方法实现 辛普森公式是数值积分中精度较高的方法,其基本思想是将积分区间分割为若干子区间,在每个子区间上应用辛普森公式,最后和得到积分近似值。公式如下: $$ \int_a^b f(x)dx \approx \frac{h}{3} \left[ f(a) + f(b) + 4\sum_{i=1}^{n/2}f(x_{2i-1}) + 2\sum_{i=1}^{n/2-1}f(x_{2i}) \right] $$ 其中: - $h = (b-a)/n$ 为步长 - $n$ 为偶数(子区间数) - $x_i = a + ih$ 为节点 #### MATLAB 实现代码 ```matlab function S = comp_simpson_integral(a, b, n, f) % 辛普森公式数值积分 % 输入: % a - 积分下限 % b - 积分上限 % n - 子区间数(必须为偶数) % f - 被积函数(函数句柄) % 输出: % S - 积分近似值 if mod(n, 2) ~= 0 error('n 必须为偶数'); end h = (b - a) / n; x = a:h:b; % 生成等距节点 y = f(x); % 计算节点函数值 % 应用辛普森公式 S = y(1) + y(end); % 端点值 S = S + 4 * sum(y(2:2:end-1)); % 奇数节点 S = S + 2 * sum(y(3:2:end-2)); % 偶数节点 S = (h/3) * S; end ``` #### 使用示例 计算 $\pi = 4\int_0^1 \frac{1}{1+x^2}dx$: ```matlab % 定义被积函数 f = @(x) 4./(1 + x.^2); % 计算不同分割数的积分值 n_values = [10, 20, 40, 80, 160]; results = zeros(size(n_values)); for i = 1:length(n_values) n = n_values(i); results(i) = comp_simpson_integral(0, 1, n, f); fprintf('n=%d: π≈%.15f, 误差=%.2e\n', n, results(i), abs(pi - results(i))); end % 绘制误差变曲线 figure; semilogy(n_values, abs(pi - results), '-o'); xlabel('分割数 n'); ylabel('误差 |π - 近似值|'); title('辛普森公式误差随n的变'); grid on; ``` #### 输出说明: - 程序计算不同分割数 $n$ 下的积分值 - 输出结果包含近似值和与真实值 $\pi$ 的误差 - 自动绘制误差随 $n$ 变的对数坐标图 - 误差随 $n$ 增大而指数级减小,体现辛普森公式的高精度特性 #### 注意事项: 1. 分割数 $n$ 必须为偶数 2. 被积函数需支持向量运算(使用 `.` 运算符) 3. 可通过增加 $n$ 提高精度,但需权衡计算效率 4. 对于震荡函数等特殊情况,可能需要自适应方法[^1] [^1]: 数值积分常用方法中,当分割数不足时可考虑自适应策略提高精度。
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

望天边星宿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值