Horner's method 霍纳法则
Contents
概述
Horner’s method 霍纳法则可减少乘法运算。有一些关于多项式求值的问题。对于多项式求值问题,我们最容易想到的算法是求出每一项的值然后把所求的值累加起来,这种算法的时间和空间效率都不高,对于数据规模不大的题目来说由于其直观、简单很容易被大家采纳,可一旦数据规模过大时,这种算法就显得无能为力了,而霍纳法则可以高效地计算多项式的值。霍纳法则是以英国数学家W.G.Horner的名字命名的,在我们中国,也被称为秦九韶算法。霍纳在19世纪就发表了这个算法。
此规则就是将多项式转换为嵌套形式,例如,当$n=5$ $$\begin{align} p^5+p^4+p^3+p^2+p \nonumber &= p \times(p^4+p^3+p^2+p+1)\\ \nonumber &=p \times \big( p \times (p^3+p^2+p^1+1)+1 \big) \\ \nonumber &=p \times \Big( p \times \big(p \times (p^2+p^1+1)+1\big)+1 \Big)\\ \nonumber &=p \times \Bigg( p \times \bigg(p \times \big( p \times (p+1) +1 \big)+1\bigg)+1 \Bigg) \end{align} $$ 转化后, 阅读起来还像更费力了, 因为有很多括号。但是这个形式有一个最大的优点: 计算效率高!
效率比较
计算式 | 乘法运算(次数) | 加法运算(次数) |
---|---|---|
$p^5+p^4+p^3+p^2+p$ | $4 + 3 + 2 + 1 = 10$ | $4$ |
$p \times \Bigg( p \times \bigg(p \times \big( p \times (p+1) +1 \big)+1\bigg)+1 \Bigg)$ | $4$ | $4$ |
乘法运算明显减少, 而加法运算次数不变。当$n=1000$ 情况如何?
计算式 | 乘法运算(次数) | 加法运算(次数) |
---|---|---|
$p^{1000}+p^{999}+ \cdots +p^{2}+p$ | $$\begin{align} \nonumber & =999+998+997+\cdots +1 \\ \nonumber &= \frac{(999+1)\times999}2 \\ \nonumber &= 499500 \end{align}$$ | $1000$ |
$p \times \Bigg( p \times \bigg(p \times \big( p \times \cdots \times (p+1) + \cdots +1 \big)+1\bigg)+1 \Bigg)$ | $1000$ | $1000$ |
时间复杂度
计算式 | 乘法运算 | 加法运算 |
---|---|---|
$p^{1000}+p^{999}+ \cdots +p^{2}+p$ | $\Large \frac{n \times(n-1)}2$ 时间复杂度:$O(n^2)$ |
$O(n)$ |
$p \times \Bigg( p \times \bigg(p \times \big( p \times \cdots \times (p+1) + \cdots +1 \big)+1\bigg)+1 \Bigg)$ | $O(n)$ | $O(n)$ |
MATLAB的horner函数测试
代码示例
$p^5+p^4+p^3+p^2+p$
|
|
$p \times \Bigg( p \times \bigg(p \times \big( p \times (p+1) +1 \big)+1\bigg)+1 \Bigg)$
|
|
通用公式
$$\begin{align} h(x) \nonumber &=a_0 + a_1\times p^1+a_2\times p^2+a_3\times p^3+ \cdots +a_n\times p^n\\ \nonumber &=a_0 + p \times \bigg(a_1+ p\times \Big(a_2 + p \times \big( a_3 + \cdots + p \times (a_{n-1}+a_n \times x) \cdots \big) \Big) \bigg) \end{align} $$
字符串进制哈希应用
字符串$S$的长度$|S|=n,n \geq 0,S[0]=S_0,S[1]=S_1,\cdots,S[i]=S_i$,哈希计算式:
$$\begin{align} hash(S) \nonumber &=s_0 + s_1\times p^1+s_2\times p^2+s_3\times p^3+ \cdots +s_{n-1}\times p^{n-1}\\ \nonumber &=s_0 + p \times \bigg(s_1+ p\times \Big(s_2 + p \times \big( s_3 + \cdots + p \times (s_{n-1}+s_n \times p) \cdots \big) \Big) \bigg) \end{align} $$
一般倒过来计算 $$\begin{align} hash(S) \nonumber &=s_0 \times p^{n-1} + s_1\times p^{n-2}+s_2\times p^{n-3}+s_3 \times p^{n-4}+ \cdots +s_{n-1}\times p^0\\ \nonumber &=s_{n-1} + p \times \bigg(s_{n-2}+ p\times \Big(s_{n-3} + p \times \big(s_{n-4} + \cdots + p \times (s_1+s_0 \times p) \cdots \big) \Big) \bigg) \end{align} $$
|
|
数据大溢出可以使用模运算
|
|
示例
$S=abcd,n=4$,质数 $p=3$
ASCII
字母 | ASCII |
---|---|
a | 97 |
b | 98 |
c | 99 |
d | 100 |
普通方式:$hash(S) =97\times p^3+98\times p^2+99\times p^1 +100 = 3898$
霍纳法则:$hash(S) =100+ p \times \big(99 + p \times (98 + 97 \times p)\big) = 3898$
参考
https://zh.wikipedia.org/zh-hans/秦九韶算法
https://en.wikipedia.org/wiki/Horner's_method
Author Shawn
LastMod 2019-11-21