题目
I
(
b
)
=
∫
0
π
/
2
1
+
(
b
2
−
1
)
cos
2
t
d
t
I(b)= \int _{0}^{\pi /2}\sqrt{1+(b^{2}-1)\cos ^{2}t}dt
I(b)=∫0π/21+(b2−1)cos2tdt
上述函数的导数为
I
′
(
b
)
=
∫
0
π
/
2
b
cos
2
t
1
+
(
b
2
−
1
)
cos
2
t
d
t
I^{\prime}(b)= \int _{0}^{\pi /2}\frac{b \cos ^{2}t}{\sqrt{1+(b^{2}-1)\cos ^{2}t}}dt
I′(b)=∫0π/21+(b2−1)cos2tbcos2tdt
采用三种方法中最好的方法计算这一积分
(1)利用数值积分的方法给出
I
(
b
)
I ( b )
I(b) 在
b
=
0
,
0.1
,
0.2
,
…
,
1
b = 0 , 0.1 , 0.2 , \dots , 1
b=0,0.1,0.2,…,1 (可以直接计算精确值的,用精确值),用Newton插值方法得到5个椭圆的周长(五个椭圆具体见上一篇图片文件的初步处理与椭圆的最小二乘拟合)。
(2)利用数值积分的方法给出
I
′
(
b
)
I^{\prime} ( b )
I′(b), 在
b
=
0
,
0.1
,
0.2
,
…
,
1
b = 0 , 0.1 , 0.2 , \dots , 1
b=0,0.1,0.2,…,1 (可以直接计算精确值的,用精确值),用Hermite插值方法得到5个椭圆的周长。
算法介绍
Netown插值
根据均差的定义,把
x
x
x看成
[
a
,
b
]
[a,b]
[a,b]上的一点,可以得到
f
(
x
)
=
f
(
x
0
)
+
f
[
x
,
x
0
]
(
x
−
x
0
)
f(x)=f(x_{0})+f \left[ x,x_{0}\right](x-x_{0})
f(x)=f(x0)+f[x,x0](x−x0)
f ( x , x 0 ) = f ( x 0 , x 1 ) + f [ x , x 0 , x 1 ] ( x − x 1 ) f ( x , x _ { 0 } ) = f ( x _ { 0 } , x _ { 1 } ) + f [ x , x _ { 0 } , x _ { 1 } ] ( x - x _ { 1 } ) f(x,x0)=f(x0,x1)+f[x,x0,x1](x−x1)
将后一个式子带入前一个式子,得到
f
(
x
)
=
f
(
x
0
)
+
f
(
x
0
)
+
f
(
x
−
x
0
)
+
f
[
x
0
,
x
0
,
x
1
]
(
x
−
x
0
)
(
x
−
x
0
)
f ( x ) = f ( x _ { 0 } ) + f ( x _ { 0 } ) + f ( x - x _ { 0 } ) + f [ x _ { 0 } , x _ { 0 } , x _ { 1 } ] ( x - x _ { 0 } ) ( x - x _ { 0 } )
f(x)=f(x0)+f(x0)+f(x−x0)+f[x0,x0,x1](x−x0)(x−x0)
再由 f [ x 1 , x 0 , x 1 ] = f [ x 0 , x 1 , x 2 ] + f [ x , x 0 , x 1 , x 2 ] ( x − x 2 ) f \left[ x_{1},x_{0},x_{1}\right] =f \left[ x_{0},x_{1},x_{2}\right] +f \left[ x,x_{0},x_{1},x_{2}\right](x-x_{2}) f[x1,x0,x1]=f[x0,x1,x2]+f[x,x0,x1,x2](x−x2)
得到
f
(
x
)
=
f
(
x
0
)
+
f
(
x
0
)
+
f
(
x
0
−
x
1
)
+
f
[
x
0
−
x
1
)
(
x
−
x
0
)
(
x
−
x
0
)
(
x
−
x
1
)
f ( x ) = f ( x _ { 0 } ) + f ( x _ { 0 } ) + f ( x _ { 0 } - x _ { 1 } ) + f [ x _ { 0 } - x _ { 1 } ) ( x - x _ { 0 } ) ( x - x _ { 0 } ) ( x - x _ { 1 } )
f(x)=f(x0)+f(x0)+f(x0−x1)+f[x0−x1)(x−x0)(x−x0)(x−x1)
+ f [ x , x 0 , x 1 , x 2 ] ( x − x 0 ) ( x − x 0 ) ( x − x 1 ) +f [x, x _ { 0 } , x _ { 1 },x_2 ] ( x - x _ { 0 } ) ( x - x _ { 0 } ) ( x - x _ { 1 } ) +f[x,x0,x1,x2](x−x0)(x−x0)(x−x1)
Hermite插值
设在结点
a
≤
x
0
<
x
1
<
⋯
<
x
n
≤
b
a \leq x _ { 0 }< x _ { 1 } < \cdots < x _ { n } \leq b
a≤x0<x1<⋯<xn≤b上
f
(
x
j
)
=
y
j
,
m
j
=
f
′
(
x
j
)
f(x_j)=y_j,m_j=f^\prime(x_j)
f(xj)=yj,mj=f′(xj),
(
j
=
0
,
1
,
⋯
,
n
)
(j=0,1,\cdots,n)
(j=0,1,⋯,n),求多项式
H
(
X
)
H(X)
H(X),满足条件
H
(
x
j
)
=
y
j
,
H
′
(
x
j
)
=
m
j
(
j
=
0
,
1
,
⋯
,
n
)
H(x_{j})=y_{j},H^{\prime}(x_{j})=m_{j}(j=0,1, \cdots ,n)
H(xj)=yj,H′(xj)=mj(j=0,1,⋯,n)
一共给出了
2
n
+
2
2n+2
2n+2个已知条件,可以唯一确定一个次数不超过
2
n
+
1
2n+1
2n+1的多项式
H
2
n
+
1
(
x
)
=
a
0
+
a
1
x
+
⋯
+
a
2
n
+
1
x
2
n
+
1
H_{2n+1}(x)=a_{0}+a_{1}x+ \cdots +a_{2n+1}x^{2n+1}
H2n+1(x)=a0+a1x+⋯+a2n+1x2n+1
低阶分段插值
为了避免插值高阶冗余现象导致逼近效果差的现象,我们可以采用分段低次插值得到不同区间内的分段函数。
代码模块
环境:python=3.9.0 sympy=1.12 numpy=1.23.5
导入模块
import sympy as sp
import numpy as np
import time
Newton插值
def Newton_Interger(data_x,formula,t):
start=time.time()
# 计算对应点的函数值
n=len(data_x)
y=[0]*n
for i in range(n):
y[i]=formula.evalf(subs={t:data_x[i]})
# 创建差商表
Z=[[0] *n for _ in range(n)]
for i in range(n):
Z[i][0]=y[i]
# 计算差商值
for i in range(n):
for j in range(1,i+1):
Z[i][j]=(Z[i][j-1]-Z[i-1][j-1])/(data_x[i]-data_x[i-j])
# 计算插值多项式
res=0
for i in range(n):
C=Z[i][i]
for j in range(i):
C*=(t-data_x[j])
res+=C
end=time.time()
print("time:",end-start)
return res.expand()
Netown法计算椭圆周长
def Compute_N(a,b):
# 构建函数
T=sp.Symbol('t')
formula=(a**2*sp.cos(T)**2+b**2*sp.sin(T)**2)**(1/2)
data_t=[0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0,1.1,\
1.2,1.3,1.4,1.5]
formula0=Newton_Interger(formula=formula,data_x=\
[data_t[0],data_t[-1]],t=T)
R0=4*Romberg(formula0,T,0,sp.pi/2,1e-6)
print(R0.evalf())
print(formula0)
formula1=Newton_Interger(formula=formula,data_x=\
[data_t[0],data_t[7],data_t[-1]],t=T)
R1=4*Romberg(formula1,T,0,sp.pi/2,1e-6)
print(R1.evalf())
print(formula1)
formula2=Newton_Interger(formula=formula,data_x=\
[data_t[0],data_t[5],data_t[10],data_t[-1]],t=T)
R2=4*Romberg(formula2,T,0,sp.pi/2,1e-6)
print(R2.evalf())
print(formula2)
formula3=Newton_Interger(formula=formula,data_x=\
[data_t[0],data_t[4],data_t[8],data_t[12],data_t[-1]],t=T)
R3=4*Romberg(formula3,T,0,sp.pi/2,1e-6)
print(R3.evalf())
print(formula3)
formula4=Newton_Interger(formula=formula,data_x=\
[data_t[0],data_t[3],data_t[6],data_t[9],data_t[12],\
data_t[-1]],t=T)
R4=4*Romberg(formula4,T,0,sp.pi/2,1e-6)
print(R4.evalf())
print(formula4)
计算结果
def Compute(a,b):
print("Compute_N:")
Compute_N(a,b)
#print("Compute_H:")
#Compute_H(a,b)
#print("Separte:")
#Separte(a,b)
Compute(a=42.8755430086675,b=40.8633914591405)
Compute(a=41.8822717617791,b=39.0938947820857)
Compute(a=40.8633914591405,b=36.5409190520717)
Compute(a=40.3106783148759,b=34.9340215298776)
Compute(a=37.2328566002455,b=30.8883836902119)
误差衡量
对于下述的椭圆形式:
x
2
a
2
+
y
2
b
2
=
1
(
a
>
0
,
b
>
0
)
.
\frac { x ^ { 2 } } { a ^ { 2 } } + \frac { y ^ { 2 } } { b ^ { 2 } } = 1 ( a > 0 , b > 0 ) .
a2x2+b2y2=1(a>0,b>0).
可以通过拉马努金椭圆计算公式快速计算出结果
C
≈
π
(
a
+
b
)
(
1
+
3
λ
2
10
+
4
−
3
λ
2
)
,
λ
=
a
−
b
a
+
b
.
C \approx \pi ( a + b ) \left( 1 + \frac { 3 \lambda ^ { 2 } } { 1 0 + \sqrt { 4 - 3 \lambda ^ { 2 } } } \right) , \lambda = \frac { a - b } { a + b } .
C≈π(a+b)(1+10+4−3λ23λ2),λ=a+ba−b.
详细代码
这里只是以Newton为例,详细代码见github代码
参考资料
[2].拉马努金椭圆计算公式