数值分析 | 多项式求值(Horner法则)

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+...+an1xn1+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(an1+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+(xr1)(a1+...+(xrn1)(an1+(xrn)(an))...)(3)
其中 r 1 , . . . , r n − 1 , r n r_1,...,r_{n-1},r_{n} r1,...,rn1,rn称为基点。如果设式(3)中参数 r 1 = . . . = r n − 1 = r n = 0 r_1=...=r_{n-1}=r_{n}=0 r1=...=rn1=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

猜你喜欢

转载自blog.csdn.net/qq_39784672/article/details/128680622