您的位置:首页 > 编程语言 > Java开发

霍纳法则和二进制幂

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

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

系数2-131-5
x=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^2
a^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),因为它是最高位系数,最高位系数只能是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的二进制形式,所以他们的有效性被削弱了,但在某种场合下,他们还是一种很有效的算法的
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息