Horner法则
又名秦九韶算法或嵌套乘法,是一种高效的多项式求值算法。
对于
n
n
n次多项式
f
(
x
)
=
a
0
+
a
1
x
+
.
.
.
+
a
n
−
1
x
n
−
1
+
a
n
x
n
(1)
f(x)=a_0+a_1x+...+a_{n-1}x^{n-1}+a_nx^n\tag{1}
f(x)=a0+a1x+...+an−1xn−1+anxn(1)
将其重写为如下形式
f
(
x
)
=
a
0
+
x
(
a
1
+
.
.
.
+
x
(
a
n
−
1
+
x
(
a
n
)
)
.
.
.
)
(2)
f(x)=a_0+x(a_1+...+x(a_{n-1}+x(a_n))...)\tag{2}
f(x)=a0+x(a1+...+x(an−1+x(an))...)(2)
求解多项式值时,由内向外计算式(2)。
对于一个 n n n次多项式,如果按照朴素算法进行计算求值(即计算式(1)),需要进行 n ( n + 1 ) 2 \pmb{\frac{n(n+1)}2} 2n(n+1)次乘法和 n \pmb{n} n次加法运算,而运用运用嵌套乘法(即计算式(2)),我们至多需要做次乘法 n \pmb{n} n和 n \pmb{n} n次加法运算,这也就体现出了horner法则的高效性,特别是通过计算机进行大规模计算时。
相比于式(2),嵌套乘法还有更一般的形式
f
(
x
)
=
a
0
+
(
x
−
r
1
)
(
a
1
+
.
.
.
+
(
x
−
r
n
−
1
)
(
a
n
−
1
+
(
x
−
r
n
)
(
a
n
)
)
.
.
.
)
(3)
f(x)=a_0+(x-r_1)(a_1+...+(x-r_{n-1})(a_{n-1}+(x-r_n)(a_n))...)\tag{3}
f(x)=a0+(x−r1)(a1+...+(x−rn−1)(an−1+(x−rn)(an))...)(3)
其中
r
1
,
.
.
.
,
r
n
−
1
,
r
n
r_1,...,r_{n-1},r_{n}
r1,...,rn−1,rn称为基点。如果设式(3)中参数
r
1
=
.
.
.
=
r
n
−
1
=
r
n
=
0
r_1=...=r_{n-1}=r_{n}=0
r1=...=rn−1=rn=0,则变成传统的嵌套形式(即式(2))。
代码实现
Matlab代码
%%嵌套乘法
%使用霍纳方法以嵌套形式计算多项式的值
%输入: 多项式的阶n,
% n+1个系数构成的数组a(第一个元素a_0为常数项),
% x坐标需要进行求值的x位置,
% 如果需要的话,还有n个基点构成的数组b
%输出: 多项式在x点对应的值y
function y=nest(n,a,x,b)
if nargin<4, b=zeros(n,1); end
y=a(n+1);
for i=n:-1:1
y = y.*(x-b(i))+a(i);
end
Python代码
"""嵌套乘法求解多项式"""
import numpy as np
def ndarrayArgs(func):
"""装饰器:函数参数list->ndarray"""
def formated(*args):
result = func(*map(lambda x: np.array(x) if isinstance(x, list) else x, args))
return result
return formated
@ndarrayArgs
def nest(n, a, x, b = None):
"""使用霍纳方法以嵌套形式计算多项式的值
:param n: 多项式的阶数
:param a: n+1个系数构成的数组(第一个元素a_0为常数项)
:param x: 需要进行求值的x坐标位置
:param b: 可选参数,由n个基点构成的数组b
:return: 多项式在x点对应的值y
"""
if b is None:
b = np.zeros(n)
y = a[n]
for i in reversed(range(n)):
y = y * (x - b[i]) + a[i]
return y
if __name__ == "__main__":
# results = nest(4, [-1, 5, -3, 3, 2], 1 / 2, [0, 0, 0, 0])
# results = nest(4, [-1, 5, -3, 3, 2], [-2, -1, 0, 1, 2])
results = nest(3, [1, 1 / 2, 1 / 2, -1 / 2], 1, [0, 2, 3])
print(results)
参考
[1] 数论 | 秦九韶算法(Horner法则) - 简书 (jianshu.com)
[2] Numerical Analysis. secondd edition. Timothy Sauer.
[3] https://github.com/riverlike14/Numerical_Analysis