霍纳法则和二进制幂
2014-01-07 01:16
183 查看
首先说一下霍纳法则,这对于多次幂来说,减少乘法是很重要的,因为相比加法,乘法的执行效率更低
我们先看一下这样一个多项式
p(x) = 2*x^4 - 1*x^3 - 3*x^2 + 1*x^1 - 5
= x ( x ( x ( 2x - 1 ) + 3 ) + 1 ) - 5
再看一下霍纳法则执行过程:
所以我们再看他的实现代码
同时霍纳法则还长生一种副产品,计算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从左到右的二进制幂运行过程
实现代码在下面
再看一下计算a^13从左到右的二进制幂运行过程
该算法效率O(logn),但由于二进制幂算法依赖指数n的二进制形式,所以他们的有效性被削弱了,但在某种场合下,他们还是一种很有效的算法的
我们先看一下这样一个多项式
p(x) = 2*x^4 - 1*x^3 - 3*x^2 + 1*x^1 - 5
= x ( x ( x ( 2x - 1 ) + 3 ) + 1 ) - 5
再看一下霍纳法则执行过程:
系数 | 2 | -1 | 3 | 1 | -5 |
x=3 | 2 | 3 * 2 +(-1)= 5 | 3 * 5 + 3 = 18 | 3 * 18 + 1 = 55 | 3 * 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的二进制位 | 1 | 1 | 0 | 1 |
累加器 | a | a^2*a=a^3 | (a^3)^2=a^6 | (a^6)^2*a=a^13 |
再看一下计算a^13从左到右的二进制幂运行过程
1 | 1 | 0 | 1 | n的二进制位 |
a^8 | a^4 | a^2 | a | 项a^2 |
a^5 * a^8 = a ^13 | a * 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),因为它是最高位系数,最高位系数只能是1 for (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的二进制形式,所以他们的有效性被削弱了,但在某种场合下,他们还是一种很有效的算法的
相关文章推荐
- 4000 HORNER(霍纳)法则的C实现以及算法比较 2.10
- 如何创建Debian二进制包(译)
- mysql中用HEX和UNHEX函数处理二进制数据的导入导出
- 可见strings能输出文件中的可打印字符串(可指定字符串的最小长度),通常用来查看非文本文件(如二进制可执行文件)中的可读内容。
- 把图片转换成二进制--把二进制转换成图片
- Win32 二进制资源格式
- 软件开发:需求分析的20条法则(转)
- Linux系统ELF文件二进制格式分析(三)
- mysql中用HEX和UNHEX函数处理二进制数据的导入导出
- 计算机编程的24条法则
- 用Java或Jsp向数据库存取二进制图片
- 把一个十进制数的二进制形式翻转,并输出翻转后所对应的十进制数
- 二进制中1的个数
- 有钱人的黄金法则
- VBS的函数集-读写二进制文件,UTF8文件,HTTP GET和POST。
- hdu 3535 AreYouBusy 多重背包~~二进制优化
- Face Alignment at 3000 FPS通俗易懂讲解二 LBP局部二进制特征(特征映射)的生成
- 35岁前成功的12条黄金法则
- 关于文本模式和二进制模式对文件进行操作的区别
- 整数的二进制形式数反转