mirror of
https://gitee.com/chfenger/goNum.git
synced 2025-12-06 16:49:24 +08:00
update comments in all of files in convenient to generate package information using `godoc` command or give tips in LiteIDE editor when the cursor keeps resting on a function or method.
156 lines
4.6 KiB
Go
156 lines
4.6 KiB
Go
// InterpLagrangeFunc_test
|
||
/*
|
||
------------------------------------------------------
|
||
作者 : Black Ghost
|
||
日期 : 2018-12-4
|
||
版本 : 0.0.0
|
||
------------------------------------------------------
|
||
求解n次拉格朗日Lagrange插值方程系数,拟合n+1个数据点
|
||
满阶插值,即阶数为给定点数-1(因不能确定非满阶时所选取的
|
||
插值点是否合理)
|
||
理论:
|
||
n omega0n+1(x)
|
||
Ln(x) = Sum(----------------------)
|
||
k=0 (x-xk)*omega1n+1(xk)
|
||
|
||
n
|
||
omega0n+1(x) = Prod(x-xi)
|
||
i=0
|
||
|
||
n
|
||
omega1n+1(xk) = Prod (xk-xi)
|
||
i=0,i!=k
|
||
|
||
参考 李信真, 车刚明, 欧阳洁, 等. 计算方法. 西北工业大学
|
||
出版社, 2000, pp 94-100.
|
||
------------------------------------------------------
|
||
输入 :
|
||
A 数据点矩阵,(n+1)x2,第一列xi;第二列yi
|
||
输出 :
|
||
B 插值系数矩阵,(n+1)x1,0~n
|
||
err 解出标志:false-未解出或达到步数上限;
|
||
true-全部解出
|
||
------------------------------------------------------
|
||
*/
|
||
|
||
package goNum_test
|
||
|
||
import (
|
||
"testing"
|
||
|
||
"github.com/chfenger/goNum"
|
||
)
|
||
|
||
//计算分母
|
||
func omega1_InterpLagrangeFunc(A goNum.Matrix, k, n int) float64 {
|
||
var sol float64 = 1.0
|
||
for i := 0; i <= n; i++ {
|
||
if i != k {
|
||
sol = sol * (A.GetFromMatrix(k, 0) - A.GetFromMatrix(i, 0))
|
||
}
|
||
}
|
||
return sol
|
||
}
|
||
|
||
//计算分子并由高阶到低阶排序
|
||
func omega0_InterpLagrangeFunc(A goNum.Matrix, k, n int) goNum.Matrix {
|
||
B := goNum.ZeroMatrix(n+1, 1)
|
||
//第零阶 x-x0
|
||
if k == 0 { //如果k==0,则从x1循环
|
||
B.SetMatrix(0, 0, -1.0*A.GetFromMatrix(1, 0))
|
||
B.SetMatrix(1, 0, 1.0)
|
||
}
|
||
if k > 0 { //如果k>0,则从x0循环
|
||
B.SetMatrix(0, 0, -1.0*A.GetFromMatrix(0, 0))
|
||
B.SetMatrix(1, 0, 1.0)
|
||
}
|
||
//其他i!=k阶
|
||
for i := 1; i <= n; i++ {
|
||
if (i != k) && ((k > 0) || ((k == 0) && (i > 1))) {
|
||
if k < i {
|
||
CA := goNum.ZeroMatrix(i+1, 1) //实际i+1行
|
||
CB := goNum.ZeroMatrix(i+1, 1) //实际i行
|
||
//先用x乘以之前每一项,相当于给每一项提升一阶,i+1
|
||
for ii := 1; ii < i+1; ii++ {
|
||
//单列可以这样,否则只能用SetMatrix和GetFromMatrix方法
|
||
CA.Data[ii] = B.Data[ii-1]
|
||
}
|
||
//再用-xi乘以B的每一有效项,i
|
||
for ii := 0; ii < i; ii++ {
|
||
//单列可以这样,否则只能用SetMatrix和GetFromMatrix方法
|
||
CB.Data[ii] = -1.0 * A.GetFromMatrix(i, 0) * B.Data[ii]
|
||
}
|
||
//同阶相加赋予B
|
||
for ii := 0; ii < i+1; ii++ {
|
||
B.Data[ii] = CA.Data[ii] + CB.Data[ii]
|
||
}
|
||
} else { // k > i
|
||
CA := goNum.ZeroMatrix(i+2, 1) //实际i+2行
|
||
CB := goNum.ZeroMatrix(i+2, 1) //实际i+1行
|
||
//先用x乘以之前每一项,相当于给每一项提升一阶,i+1
|
||
for ii := 1; ii < i+2; ii++ {
|
||
//单列可以这样,否则只能用SetMatrix和GetFromMatrix方法
|
||
CA.Data[ii] = B.Data[ii-1]
|
||
}
|
||
//再用-xi乘以B的每一有效项,i+1
|
||
for ii := 0; ii < i+1; ii++ {
|
||
//单列可以这样,否则只能用SetMatrix和GetFromMatrix方法
|
||
CB.Data[ii] = -1.0 * A.GetFromMatrix(i, 0) * B.Data[ii]
|
||
}
|
||
//同阶相加赋予B
|
||
for ii := 0; ii < i+2; ii++ {
|
||
B.Data[ii] = CA.Data[ii] + CB.Data[ii]
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|
||
return B
|
||
}
|
||
|
||
// InterpLagrangeFunc 求解n次拉格朗日Lagrange插值方程系数,拟合n+1个数据点
|
||
func InterpLagrangeFunc(A goNum.Matrix) (goNum.Matrix, bool) {
|
||
/*
|
||
求解n次拉格朗日Lagrange插值方程系数,拟合n+1个数据点
|
||
输入 :
|
||
A 数据点矩阵,(n+1)x2,第一列xi;第二列yi
|
||
输出 :
|
||
B 插值系数矩阵,(n+1)x1
|
||
err 解出标志:false-未解出或达到步数上限;
|
||
true-全部解出
|
||
*/
|
||
|
||
//阶数
|
||
n := A.Rows - 1
|
||
|
||
B := goNum.ZeroMatrix(n+1, 1) //最终系数矩阵
|
||
var err bool = false
|
||
|
||
//计算系数矩阵
|
||
for k := 0; k <= n; k++ {
|
||
//1. 计算分母和系数乘积
|
||
temp0 := A.GetFromMatrix(k, 1) / omega1_InterpLagrangeFunc(A, k, n)
|
||
//2. 计算分子并乘以上一步的结果,由高阶到低阶排序
|
||
temp1 := omega0_InterpLagrangeFunc(A, k, n)
|
||
for i := 0; i < temp1.Rows; i++ {
|
||
temp1.Data[i] = temp1.Data[i] * temp0
|
||
}
|
||
//3. 累加
|
||
for i := 0; i < B.Rows; i++ {
|
||
B.Data[i] += temp1.Data[i]
|
||
}
|
||
}
|
||
|
||
err = true
|
||
return B, err
|
||
}
|
||
|
||
func BenchmarkInterpLagrangeFunc(b *testing.B) {
|
||
A23 := goNum.NewMatrix(3, 2, []float64{0.0, 1.0,
|
||
1.0, 2.0,
|
||
2.0, 3.0})
|
||
for i := 0; i < b.N; i++ {
|
||
InterpLagrangeFunc(A23)
|
||
}
|
||
}
|