霍纳法则和二进制幂

来源:互联网 发布:ed hardy正品网络购买 编辑:程序博客网 时间:2024/05/16 04:39

首先说一下霍纳法则,这对于多次幂来说,减少乘法是很重要的,因为相比加法,乘法的执行效率更低


我们先看一下这样一个多项式

             p(x)  =  2*x^4 - 1*x^3 - 3*x^2 + 1*x^1 - 5

                     = x ( x ( x ( 2x - 1 ) + 3 ) + 1 ) - 5


再看一下霍纳法则执行过程:

系数2-131-5x=323 * 2 +(-1)= 53 * 5 + 3 = 183 * 18 + 1 = 553 * 55 + (-5)= 160


所以我们再看他的实现代码

/** * 霍纳法则 *  * @author chenxuegui */public class HornerRule{public static void main(String[] args){int[] a = new int[] { 2, -1, 3, 1, -5 };int x = 3;System.out.println(Horner(a, x));}/** * 霍纳法则的核心 *  * 如果 p(x) = 2*x^4 + x^3 - 3*x^2 + x -5 = x(x(x(2x-1)+3)+1)-5 *  * 则数组  2 -1 3 1 -5 (次序幂告到低) *  * @param a * @param x * @return */private static int Horner(int[] a, int x){int result = a[0];for (int i = 1; i < a.length; i++){result = result * x + a[i];}return result;}}



同时霍纳法则还长生一种副产品,计算p(x) 在某点上的值x0时所产生的中间数,恰好可以作为p(x)除以x-x0的商的系数,而算法的最后结果,除了等于p(x0)以外,还等于这个除法的余数,对本例,  p(x)  =  2*x^4 - 1*x^3 - 3*x^2 + 1*x^1 - 5 除以 x - 3 的商为  p(x)  =  2*x^3 + 5*x^2 + 18*x^1 + 55,余数为160 ,这方法逼长除法方便



接下来看一下二进制幂

二进制幂他是一种霍纳法则在幂上的应用 

                  a^n = a^p(2) = a^( bi * 2 ^ i + ....+ b1 * 2 ^ 1)


二进制幂运算有两种实现,一种是从左到右,一种是从右到左

看一下计算a^13从左到右的二进制幂运行过程

n的二进制位1101累加器aa^2*a=a^3(a^3)^2=a^6(a^6)^2*a=a^13

实现代码在下面

再看一下计算a^13从左到右的二进制幂运行过程

1101n的二进制位a^8a^4a^2a项a^2a^5 * a^8 = a ^13a * a^4 = a^5 a累加器

/** * 二进制幂 其实核心还是使用霍纳法则的变形 *  * @author chenxuegui *  */public class BinaryExponentiation{public static void main(String[] args){// 计算3^13次System.out.println(leftRightBinaryExponentiation(3, new int[] { 1, 1,0, 1 }));/*System.out.println(rightLeftBinaryExponentiation(3, new int[] { 1, 1,0, 1 }));*/}/** *  * 如 a^13 = a^(1*2^3 + 1*2^2 + 0*2^1 + 1*2^0) *  * @param a *            底数 * @param b *            幂二进制霍纳表达式(数组顺序幂次高到底) */private static int leftRightBinaryExponentiation(int a, int[] b){int product = a;// b[0]一定为1(要么为1,要么为0),因为它是最高位系数,最高位系数只能是1for (int i = 1; i < b.length; i++){product = product * product;if (b[i] == 1)product *= a;}return product;}/** *  * 如 a^13 = a^(1*2^3 + 1*2^2 + 0*2^1 + 1*2^0) *  * @param a *            底数 * @param b *            幂二进制霍纳表达式(数组顺序幂次高到底) * @return */private static int rightLeftBinaryExponentiation(int a, int[] b){int product = 1;int term = a;for (int i = b.length-1; i >=0 ; i--){if(b[i] == 1)product *=term;term *= term;}return product;}}


该算法效率O(logn),但由于二进制幂算法依赖指数n的二进制形式,所以他们的有效性被削弱了,但在某种场合下,他们还是一种很有效的算法的




0 0
原创粉丝点击