• 霍纳法则和二进制幂


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


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

                 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的二进制形式,所以他们的有效性被削弱了,但在某种场合下,他们还是一种很有效的算法的




  • 相关阅读:
    POJ 3258 二分答案
    Prototype 模式示例代码 (C++)
    offsetof 和 container_of
    二进制整数中的“1”
    Binary Tree Traversal Algorithms (二叉树遍历算法)
    A* Pathfinding Algorithm
    Axis­ Aligned 
Rectangles (Google 面试题, 2016网易游戏校招笔试)
    [LeetCode] Burst Ballons
    C++ 继承语义下构造函数中的对象指针
    kill-9和kill-15的区别
  • 原文地址:https://www.cnblogs.com/riasky/p/3509097.html
Copyright © 2020-2023  润新知