插值复习(计算方法_python实现)

1. 题目

4、给出x,y数据位于机翼剖面的轮廓线上,y1和y2分别对应轮廓的上下线。假设需要得到x坐标每改变0.1时的y坐标。试完成加工所需数据,画出曲线,并求机翼剖面的面积。
在这里插入图片描述

2.算法描述

解题思路:运用学过的插值算法,对区间x所在的区间 [0,
15]内进行插值拟合,为了提高解题的准确度,把步长由0.1的150个点增加到了1000个点,具体做法为:
通过调用numpy库里的linspace函数随机产生了1000个点得等差数列,所求的结果存入另外两个列表里面,最后运用梯形积分求出不同插值情况下的面积,
算法流程图如下所示:

1.拉格朗日插值:
在这里插入图片描述
2.牛顿插值:
在这里插入图片描述
3.分段线性插值:
在这里插入图片描述
4.三次样条插值
在这里插入图片描述

3.源代码

#!/usr/bin/env python
# coding=utf-8

import matplotlib.pyplot as plt
import numpy as np

#牛顿插值
def newton_interpolation(X, Y, x):

    sum = Y[0]
    temp = np.zeros((len(X), len(X)))

    for i in range(0, len(X)):
        temp[i, 0] = Y[i]
    temp_sum = 1.0

    for i in range(1, len(X)):
        temp_sum = temp_sum * (x - X[i - 1])
        for j in range(i, len(X)):
            temp[j, i] = (temp[j, i - 1] - temp[j - 1, i - 1]) / (X[j] - X[j - i])
        sum += temp_sum * temp[i, i]
    return sum

#拉格朗日插值
def laGeLangRi(x, y, a) :
    ans = 0.0
    for i in range(len(y)) :
        t = y[i]
        for j in range(len(y)) :
            if i != j :
                t *= (a - x[j]) / (x[i] - x[j])
        ans += t
    return ans

#分段线性插值
def fenDuanXianXingChaZhi(X, Y, a):
    a = [a] if isinstance(a, (float, int)) else a
    x_loc = np.searchsorted(X, a)

    res_lst = []
    for x, i in zip(a, x_loc):
        L_i = Y[i - 1] * (x - X[i]) / (X[i - 1] - X[i]) + \
              Y[i] * (x - X[i - 1]) / (X[i] - X[i - 1])
        #res_lst.append(L_i)
        res_lst = L_i
    return res_lst

X = [0, 3, 5, 7, 9, 11, 12, 13, 14, 15]
Y = [0, 1.8, 2.2, 2.7, 3.0, 3.1, 2.9, 2.5, 2.0, 1.6]
Y1 = [0, 1.2, 1.7, 2.0, 2.1, 1.8, 1.2, 1.1, 1.0, 1.6]

import scipy.interpolate as spi

xs = np.linspace(np.min(X), np.max(X), 1000, endpoint=True)
#xs = np.arange(np.min(X), np.max(X), 0.1)

print(xs)
#三次样条插值
#ipo1 = spi.splrep(X, Y, k = 1)
#iy1 = spi.splev(xs, ipo1)

ipo3 = spi.splrep(X, Y, k = 3)
Y1_ipo3 = spi.splrep(X, Y1, k = 3)
san1 = spi.splev(xs, ipo3)
Y1_ipo3 = spi.splrep(X, Y1, k = 3)
san2 = spi.splev(xs, Y1_ipo3)

#A = get_diff_table(X, Y)
#df = pd.DataFrame(A)

#xs = np.linspace(np.min(X), np.max(X), 1000, endpoint=True)
#print(xs)
#xs = np.arange(np.min(X), np.max(X), 0.1)
niu1 = []
niu2 = []
la1 = []
la2 = []
f1 = []
f2 = []

for x in xs:
    niu1.append(newton_interpolation(X, Y, x))
    niu2.append(newton_interpolation(X, Y1, x))
    
    la1.append(laGeLangRi(X, Y, x))
    la2.append(laGeLangRi(X, Y1, x))
    f1.append(fenDuanXianXingChaZhi(X, Y, x))
    f2.append(fenDuanXianXingChaZhi(X, Y1, x))

#print(len(xs))
#print(f2)

test = []
test1 = []
test2 = []
test3 = []

tmp1 = []
#梯形面积公式
def Area() :
    sum, sum1, sum2, sum3 = 0.0, 0.0, 0.0, 0.0
    #for i in range(0, 27) :
    for i in range(0, len(xs)) :
        test1.append(la2[i] - la1[i])
        test2.append(niu2[i] - niu1[i])
        test.append(f1[i] - f2[i])
        test3.append(san1[i] - san2[i])

    for i in range(1, len(xs)) :
        sum += (xs[i] - xs[i - 1]) / 2.0 * (test[i - 1] + test[i])
        sum1 += (xs[i] - xs[i - 1]) / 2.0 * (test1[i - 1] + test1[i])
        sum2 += (xs[i] - xs[i - 1]) / 2.0 * (test2[i - 1] + test2[i])
        sum3 += (xs[i] - xs[i - 1]) / 2.0 * (test3[i - 1] + test3[i])

    tmp = 0.0
    for i in range(0, len(X)) :
        tmp1.append(Y[i] - Y1[i])
    for i in range(1, len(X)) :
        tmp += (X[i] - X[i - 1]) / 2.0 * (tmp1[i - 1] + tmp1[i])

    print('最初的面积     : %.15f' % tmp)
    print('拉格朗日插值   : %.15f' % sum1)
    print('牛顿插值       : %.15f' % sum2)
    print('分段插值       :', sum)
    print('三次样条插值   :', sum3)

Area()

#拉格朗日插值_图像
plt.title("laGeLangRi")
plt.plot(X, Y, 'r', label="original")
plt.plot(X, Y1, 'r', label = 'original')
plt.plot(xs, la1, 'b', linestyle = '--', label='la1')
plt.plot(xs, la2, 'b', linestyle = '--', label='la2')
plt.xlabel('x')
plt.ylabel('y')
plt.legend(loc='best')
plt.savefig('laGeLangRi')
plt.show()
#plt.clf()

#牛顿插值_图像
plt.title('Newton')
plt.plot(X, Y, 'r', label="original")
plt.plot(X, Y1, 'r', label = 'original')
plt.plot(xs, niu1, 'gray', linestyle = '--', linewidth = 3, label='niu1')
plt.plot(xs, niu2, 'gray', linestyle = '--', linewidth = 3, label='niu2')
plt.xlabel('x')
plt.ylabel('y')
plt.legend(loc='best')
plt.savefig('Newton')
plt.show()
#plt.clf()

#分段线性插值_图像
plt.title('fenDuanXianXing')
plt.plot(X, Y, 'r', label="original")
plt.plot(X, Y1, 'r', label = 'original')
plt.plot(xs, f1, 'gray', linestyle = '--', linewidth = 3, label='f1')
plt.plot(xs, f2, 'gray', linestyle = '--', linewidth = 3, label='f2')
plt.xlabel('x')
plt.ylabel('y')
plt.legend(loc='best')
plt.savefig('fenDuanXianXing')
plt.show()
#plt.clf()

#三次样条插值_图像
plt.title('sanCiYangTiao')
plt.plot(X, Y, 'b', label='original')
plt.plot(X, Y1, 'b', label='original')
##plt.scatter(new_x, iy1, label = 'Y = iy1')
plt.plot(xs, san1, 'r', linestyle = '--', label = 'san1')
plt.plot(xs, san2, 'r', linestyle = '--', label = 'san2')
plt.xlabel('x')
plt.ylabel('y')
plt.legend(loc='best')
plt.savefig('sanCiYangTiao')
plt.show()
plt.clf()

4.实验结果分析

在这里插入图片描述
在这里插入图片描述
应用梯形积分求得11个点所对应的面积为:11.750000000000000,对比拉格朗日插值、牛顿插值、分段线性插值、三次样条插值的图形和面积后可以得到,拉格朗日插值法和牛顿插值法产生了非常严重的龙格现象,与实际不符,拉格朗日插值法和牛顿插值法的收敛性无法得到保证, 二者求得的面积分别为:36.239333846993190, 36.239333846993254;分段线性插值的大致图形与原图相近,求得的面积为:11.749972945918891,但它得到的曲线不是很光滑,用带棱角的曲线制作飞机机翼是不可取的;为了解决在结点处保持光滑的问题,引入了三次样条插值,观察图形后可以发现,三次样条插值较为光滑,产生的误差较小,求得的面积为:12.240309390279387。

  • 4
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
#include <iostream> #include <cmath> #include <fstream> using namespace std; class scyt { float *x,*y,*d,*h,*u,*q,*a,*b,*c,*l,*r,*o,*M; int m; float y0,y3; public: scyt(); void qiudao(); void zgf(); void qiujie(); ~scyt(); }; void main() { scyt hello; hello.qiudao(); hello.zgf(); hello.qiujie(); } scyt::scyt() { ifstream fin("三次样条插值.txt"); for(float j;fin>>j;) { m=int(j); break; } x=new float[m]; y=new float[m]; d=new float[m]; h=new float[m-1]; u=new float[m-2]; q=new float[m-2]; a=new float[m-1]; b=new float[m]; c=new float[m-1]; l=new float[m]; r=new float[m-1];//此处的r为追赶法中的u; o=new float[m];//此处o为追赶法中的y M=new float[m];//此处M为追赶法中的x; int jishu=0; for(j;fin>>j;) { if(jishu<=m-1) x[jishu]=j; if(jishu>m-1&&jishu;<2*m) { y[jishu-m]=j; } if(jishu==2*m) { y0=j; } if(jishu==2*m+1) { y3=j; } jishu++; } fin.close(); } void scyt::qiudao() { for(int i=0;i<m-1;i++) { h[i]=x[i+1]-x[i]; } for(i=0;i<m-2;i++) { u[i]=h[i] / (h[i] + h[i+1]); } for(i=0;i<m-2;i++) { q[i]=1-u[i]; } d[0]=6/h[0]*((y[1]-y[0])/h[0]-y0); for(i=1;i<m-1;i++) { d[i]=6/(h[i-1]+h[i])*((y[i+1]-y[i])/h[i]-((y[i]-y[i-1])/h[i-1])); } d[m-1]=6/h[m-2]*(y3-(y[m-1]-y[m-2])/h[m-2]); } void scyt::zgf() { u[m-2]=1; for(int i=0;i<m;i++) { b[i]=2; } c[0]=1; for(i=1;i<m-1;i++) { c[i]=q[i-1]; } //........................................ l[0]=b[0]; for(i=0;i<m-1;i++) { r[i]=c[i] / l[i]; l[i+1]=b[i+1] - (u[i] * r[i]); } o[0]=d[0] / l[0]; for(i=1;i<m;i++) { o[i]=(d[i]-u[i-1]*o[i-1]) / l[i]; } M[m-1]=o[m-1]; for(i=m-2;i>=0;i--) { M[i]=o[i]-r[i] * M[i+1]; } cout<<m<<"个点的导数值分别是:"<<endl; for(i=0;i<m;i++) { cout<<"M"<<i+1<<"="; cout<<M[i]<<endl; } //M的值求出。。。。。。追赶法调用完毕 } void scyt::qiujie() { float S; for(;;) { float f; cout<<"请输入待求x的值(输入1000)时退出:"; cin>>f; if(f==1000) break; for(int i=0;i<m;i++) { if(f>x[i]&&f<x[i+1]) { S=pow((x[i+1]-f),3)*M[i]/(6*h[i]) + pow(f-x[i],3)*M[i+1]/(6*h[i]) + (x[i+1]-f)*(y[i]-h[i]*h[i]*M[i]/6)/h[i] + (f-x[i])*(y[i+1]-h[i]*h[i]*M[i+1]/6)/h[i]; cout<<"S["<<f<<"]="<<S<<endl; } } } } scyt::~scyt() { delete []x,y,d,h,u,q,a,b,c,l,r,o,M; }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值