请教高手用VB把牛顿迭代和样条算法做下 要是把数值积分做出来追加100分
參考答案:例4.用牛顿迭代法求一元三次方程f(x)=aX3+bx2+cx+d=0的根。
f(x)=aX3+bx2+cx+d
g(x)=f'(x)=3aX2+2bx+c
其VB程序如下:
x0 = 1
Do Until Abs(x - x0) <= y
x = x0
f = a * x ^ 3 + b * x ^ 2 + c * x + d
g = 3 * a * x ^ 2 + 2 * b * x + c
x0 = x - f / g
Loop
Print x0
方程的系数a、b、c、d和根的精度y是已知的,或由用户输入。
具体使用迭代法求根时应注意以下两种可能发生的情况:
(1) 如果方程无解,算法求出的近似根序列就不会收敛,迭代过程会变成死循环,因此在使用迭代算法前应先考察方程是否有解,并在程序中对迭代的次数给予限制;
(2) 方程虽然有解,但迭代公式选择不当,或迭代的初始近似根选择不合理,也会导致迭代失败。
Option Explicit
'======================================================================
'实现不同方程的牛顿迭代法 和 一些基本复变函数
'======================================================================
Public Const PI = 3.14159265358979
Public Const e = 2.***********
Function MMi(x0 As Double, y0 As Double, nN As Long, M As Long, _
nM As Long, Hx As Double, Hy As Double, dL1 As Double, _
dL2 As Double, dL3 As Double, dL4 As Double) As Long
'调用时MMi(x0, y0, Int(SeData(0, 13)), M, nM, dX, dY, dL1, dL2, dL3, dL4)
'实现不同方程的牛顿迭代法,并返回方程的各种基本性质
' 牛顿迭代法解方程原理:
' 不失一般性设方程为: f(Z) = 0 (关于复数Z的函数)
' 对 f(Z) 求导函数得: f'(Z)
' 对任意复数Z0可以有Z1 , Z1 = Z0 - f(Z0)/f'(Z0)
' 同样,对复数Z1可以有Z2 , Z2 = Z1 - f(Z1)/f'(Z1)
' …… …… ……
' 则,有迭代式:Z(n+1)=Z(n)-f(Z(n))/f'(Z(n))
' 对于选定的起始点,迭代大多都会收敛于方程f(z) = 0 的某个根,
' 这就是牛顿迭代法解方程的基本方式;
' 但也可能存在许多点,使迭代根本就不会收敛,
' 甚至可能出现混沌的状态。
'dX 第一次迭代x轴的变化率
'dY 第一次迭代y轴的变化率
'dL1 第一次迭代移动距离
'dL2 第nM次迭代移动距离
'dL3 第nM次迭代距离(0,0)点的距离
'dL4 迭代得到解以后距离解的大概距离
Dim x1 As Double, x2 As Double, y1 As Double, y2 As Double
Dim m0 As Double, i As Long, k As Long
Dim SeTa1 As Double, SeTa2 As Double, P1 As Double
Dim P2 As Double, A As Double, B As Double
Dim temp1 As Double, temp2 As Double, temp3 As Double, temp4 As Double, temp5 As Double
Dim temp6 As Double, temp7 As Double, temp8 As Double, temp9 As Double, temp0 As Double
Dim R1 As Double, R2 As Double
Dim Sum As Long 'Sum值用来判断迭代是否已经到达根(方程的解),这是一种比较好的方式
Dim bx As Double, by As Double, xb As Double, yb As Double
Dim N As Long, N7 As Double
On Error GoTo aaa:
x1 = x0: y1 = y0
N = Int(SeData(0, 14))
N7 = 0.01
Sum = 0
Select Case nN
Case 1 '方程 Z^N-1=0
For i = 1 To M
P1 = Sqr(x1 * x1 + y1 * y1)
SeTa1 = ZArg(x1, y1, 0)
x2 = ((N - 1) * P1 * Cos(SeTa1) + P1 ^ (1 - N) * Cos((1 - N) * SeTa1)) / N
y2 = ((N - 1) * P1 * Sin(SeTa1) + P1 ^ (1 - N) * Sin((1 - N) * SeTa1)) / N
temp0 = Abs(Abs(x1) - Abs(x2)) ^ 2 + Abs(Abs(y1) - Abs(y2)) ^ 2
If temp0 < N7 Then
Sum = Sum + 1
If Sum > 2 Then
dL4 = (temp0) / N7
If i > nM Then
Exit For
End If
End If
End If
If i = 1 Then
Hx = Abs(x1 - x2): Hy = Abs(y1 - y2)
dL1 = (Hx ^ 2 + Hy ^ 2) ^ 0.5
End If
If i = nM Then
dL2 = ((x1 - x2) ^ 2 + (y1 - y2) ^ 2) ^ 0.5
dL3 = (x2 ^ 2 + y2 ^ 2) ^ 0.5
End If
x1 = x2: y1 = y2
Next i
MMi = (k - 1) * M / N + i
Case 2, 0 '方程 Z^3-1=0 的特解
x1 = -x1 '其实没有必要,这里做了一下水平翻转
For i = 1 To M
x2 = x1: y2 = y1: m0 = (x1 * x1 + y1 * y1) ^ 2
If (x1 * x1 * x1 - x1 * y1 * y1 * 3 - 1) ^ 2 _
+ (x1 * x1 * y1 * 3 - y1 * y1 * y1) ^ 2 < N7 Then
dL4 = Abs(Sqr(x1 * x1 + y1 * y1) - 1) / N7
If i > nM Then
Exit For
End If
End If
x1 = x2 - (x2 + y2) / 6 + (x2 * x2 - y2 * y2 - x2 * y2 * 2) / 6 / m0
y1 = y2 + (x2 - y2) / 6 + (y2 * y2 - x2 * x2 - x2 * y2 * 2) / 6 / m0
If i = 1 Then
Hx = Abs(x1 - x2): Hy = Abs(y1 - y2)
dL1 = (Hx ^ 2 + Hy ^ 2) ^ 0.5
End If
If i = nM Then
dL2 = ((x1 - x2) ^ 2 + (y1 - y2) ^ 2) ^ 0.5
dL3 = (x1 ^ 2 + y1 ^ 2) ^ 0.5
End If
Next i
If x1 > 0.9 Then
MMi = i + 1 * 0.33 * M
ElseIf y1 > 0.8 Then
MMi = i + (0.33 + 1 * 0.33) * M
ElseIf y1 < -0.8 Then
MMi = i + (0.66 + 0.33 * 1) * M
End If
Case 3 '方程 Z*(1+Z^A)/(1-Z^A)=R
bx = x0: by = y0
A = SeData(0, 15) ': B = SeData(0, 16)
R1 = SeData(0, 17): R2 = SeData(0, 18)
For i = 1 To M
temp1 = bx: temp2 = by
Call Zfang(temp1, temp2, A, temp3, temp4)
Call Zji(temp3, temp4, temp1, temp2, temp5, temp6)
Call Zji(temp3, temp4, R1, R2, temp7, temp8)
temp5 = temp5 + temp7 - R1 + temp1
temp6 = temp6 + temp8 - R2 + temp2
Call Zshang(temp3, temp4, temp1, temp2, temp7, temp8)
temp7 = temp7 + 1 + (A + 1) * temp3
temp8 = temp8 + (A + 1) * temp4
Call Zshang(temp5, temp6, temp7, temp8, temp3, temp4)
bx = temp1 - temp3
by = temp2 - temp4
temp0 = Abs(Abs(bx) - Abs(temp1)) ^ 2 + Abs(Abs(by) - Abs(temp2)) ^ 2
If temp0 < N7 Then
Sum = Sum + 1
If Sum > 2 Then
dL4 = (temp0) / N7
If i > nM Then
Exit For
End If
End If
End If
If i = 1 Then
Hx = Abs(bx - temp1): Hy = Abs(by - temp2)
dL1 = (Hx ^ 2 + Hy ^ 2) ^ 0.5
End If
If i = nM Then
dL2 = ((bx - temp1) ^ 2 + (by - temp2) ^ 2) ^ 0.5
dL3 = (bx ^ 2 + by ^ 2) ^ 0.5
End If
Next i
MMi = i
End Select
Exit Function
aaa:
MMi = i
End Function
'一些复变函数
'============================
'Z1^Z2 (复数的复数次方)
Public Sub ZZFang(x1 As Double, y1 As Double, x2 As Double, y2 As Double, k As Double, x As Double, y As Double)
Dim T As Double, TT As Double
Dim P As Double, Fai As Double
On Error Resume Next
P = Sqr(x1 * x1 + y1 * y1)
If P = 0 Then
x = 0: y = 0
Exit Sub
End If
Fai = ZArg(x1, y1, k)
T = P ^ x2 * e ^ (-y2 * Fai)
TT = Log(P) * y2 + x2 * Fai
x = T * Cos(TT)
y = T * Sin(TT)
End Sub
'Z1*Z2 (复数乘积)
Public Sub Zji(x1 As Double, y1 As Double, x2 As Double, y2 As Double, x As Double, y As Double)
x = x1 * x2 - y1 * y2
y = x1 * y2 + y1 * x2
End Sub
'Z1/Z2 (复数商)
Public Sub Zshang(x1 As Double, y1 As Double, x2 As Double, y2 As Double, x As Double, y As Double)
Dim T As Double
T = x2 * x2 + y2 * y2
If T = 0 Then
If x1 = 0 Then
x = 1
y = 1
Else
x = Sgn(x1) * 1E+50
y = Sgn(y1) * 1E+50
End If
Else
x = (x1 * x2 + y1 * y2) / T
y = (-x1 * y2 + y1 * x2) / T
End If
End Sub
'Z^N (复数的实数次方)
Public Sub Zfang(x1 As Double, y1 As Double, N As Double, x As Double, y As Double)
Dim T As Double, TT As Double, AtnYX As Double
T = Sqr(x1 * x1 + y1 * y1)
AtnYX = Atn(y1 / x1)
If x1 < 0 Then
TT = PI + AtnYX
ElseIf y1 > 0 Then
TT = AtnYX
Else 'if y1<=0 then
TT = PI * 2# + AtnYX
End If
T = T ^ N
TT = TT * N
x = T * Cos(TT)
y = T * Sin(TT)
End Sub
'Arg(Z) (复数的辐角)
Public Function ZArg(x As Double, y As Double, k As Double) As Double
If x = 0 Then
If y = 0 Then
ZArg = 0
ElseIf y > 0 Then
ZArg = PI / 2#
Else 'if y<0 then
ZArg = PI * 1.5
End If
ElseIf x > 0 Then
ZArg = Atn(y / x)
If ZArg < 0 Then ZArg = PI * 2 + ZArg
Else 'if x<0 then
ZArg = Atn(y / x) + PI
End If
ZArg = ZArg + PI * 2 * k
End Function
'为了实现 Mandelbrot 特效定义的函数 (其实就是Mandelbrot函数迭代)
Public Sub fz2(x0 As Double, y0 As Double, xx As Double, yy As Double, x As Double, y As Double, N As Long)
Dim t1 As Double, t2 As Double, t3 As Double, t4 As Double
Dim i As Long
t1 = x0: t2 = y0
For i = 1 To N
t3 = t1 * t1 - t2 * t2 + xx
t4 = 2 * t1 * t2 + yy
t1 = t3: t2 = t4
Next i
x = t1: y = t2
End Sub