-
Notifications
You must be signed in to change notification settings - Fork 44
/
Muller_test.go
129 lines (115 loc) · 3.19 KB
/
Muller_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// Muller_test
/*
------------------------------------------------------
作者 : Black Ghost
日期 : 2018-12-20
版本 : 0.0.0
------------------------------------------------------
Muller法求解非线性方程f(x)=0的解
理论:
参考 John H. Mathews and Kurtis D. Fink. Numerical
methods using MATLAB, 4th ed. Pearson
Education, 2004. ss 2.5.2.
------------------------------------------------------
输入 :
fun 求解函数
x0 初值自变量,三个不同点,3x1
tol 控制误差
n 最大迭代步数
输出 :
sol 解
err 解出标志:false-未解出或达到步数上限;
true-全部解出
------------------------------------------------------
*/
package goNum_test
import (
"math"
"testing"
"github.com/chfenger/goNum"
)
// Muller Muller法求解非线性方程f(x)=0的解
func Muller(fun func(float64) float64, x0 goNum.Matrix, tol float64, n int) (float64, bool) {
/*
Muller法求解非线性方程f(x)=0的解
输入 :
fun 求解函数
x0 初值自变量,三个不同点,3x1
tol 控制误差
n 最大迭代步数
输出 :
sol 解
err 解出标志:false-未解出或达到步数上限;
true-全部解出
*/
//判断tol
if tol <= 0.0 {
panic("Error in goNum.Muller: tol less than or euqals to zero")
}
var sol float64
var err bool = false
//x0赋给p0并计算对应的y0
p0 := goNum.ZeroMatrix(x0.Rows, x0.Columns+1)
x0sort, _ := goNum.MinMaxSort(x0.Data)
for i := 0; i < x0.Rows; i++ {
p0.SetMatrix(i, 0, x0sort[i])
p0.SetMatrix(i, 1, fun(x0sort[i]))
}
//迭代计算
for i := 0; i < n; i++ {
//准备系数
h0 := p0.GetFromMatrix(0, 0) - p0.GetFromMatrix(2, 0)
h1 := p0.GetFromMatrix(1, 0) - p0.GetFromMatrix(2, 0)
c := p0.GetFromMatrix(2, 1)
e0 := p0.GetFromMatrix(0, 1) - c
e1 := p0.GetFromMatrix(1, 1) - c
b := h1*h0*h0 - h0*h1*h1
a := (e0*h1 - e1*h0) / b
b = (e1*h0*h0 - e0*h1*h1) / b
//求根
z2 := b*b - 4.0*a*c
if z2 < 0 {
//panic("Error in goNum.Muller: There is complex values exist")
z2 = 0
}
var z float64
if b < 0 {
z = -2.0 * c / (b - math.Sqrt(z2))
}
z = -2.0 * c / (b + math.Sqrt(z2))
z = p0.GetFromMatrix(2, 0) + z
//判断解
if math.Abs(fun(z)) < tol {
err = true
sol = z
return sol, err
}
//删除离z最远的点
dis := []float64{
z - p0.GetFromMatrix(0, 0),
z - p0.GetFromMatrix(1, 0),
z - p0.GetFromMatrix(2, 0)}
_, deli, _ := goNum.MaxAbs(dis)
for j := 0; j < 3; j++ {
if deli == j {
p0.SetMatrix(j, 0, z)
}
}
x0sort, _ = goNum.MinMaxSort(p0.ColumnOfMatrix(0))
for j := 0; j < 3; j++ {
p0.SetMatrix(j, 0, x0sort[j])
p0.SetMatrix(j, 1, fun(x0sort[j]))
}
}
err = false
return sol, err
}
func fun44(x float64) float64 {
return x*x*x - 3.0*x + 2.0
}
func BenchmarkMuller(b *testing.B) {
x44 := goNum.NewMatrix(3, 1, []float64{2.0, 3.0, 4.0})
for i := 0; i < b.N; i++ {
goNum.Muller(fun44, x44, 1e-12, 1e6)
}
}