数值的整数次方

题目描述

给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。


题目分析

        这道题目看似简单,很多人都可以在30秒就写出传统的代码,如下:

public double powerWithExponent(double base,int exponent){  
        double result = 1.0;  
        for(int i = 1;i<= exponent;i++){  
            result = result*base;  
        }  
        return result;  
    }  
但是,这个代码并没有考虑到输入的指数小于1即为0或者负数的情况。当我们知道指数为负数的时候,可以先求指数的绝对值,然后算出次方的结果之后再取倒数。既然需要求倒数,那么自然就要想到对0求倒数如何处理,在Java中我们可以用抛出异常的方法来处理。同时还需要指出,由于0的0次方在数学上是没有意义的,所以无论输出0还是1都可以接受,但是需要跟面试官说清楚。还有一个需要注意的点,判断double类型的底数是否为0,不能直接用base==0判断,因为计算机内表示小数(double和float)的时候都有误差,判断两个小数是否相等,只能判断它们的差的绝对值是否在一个很小的范围内,如果是,则可以认为二者相等。
在效率上继续考虑优化,若用上述传统的累乘的方法求次方,当exponent很大的时候,需要循环做很多次乘法,这是很低效的,

因此我们可以用如下公式求a的n次方:


通过这个公式,就可以递归的实现求a的n次方了,减少乘法的循环次数。既然要优化代码,那我们就优化的极致:我们知道位运算相比乘、除、求模运算效率更高,所以在方法内部,我们用右移一位来代替“除以2”,用与1按位与运算来代替求模运算进而判断指数是否为奇数。

public class Power {

	
		public double power(double base, int exponent) throws Exception {
	        double result = 0.0;
	        //底数为0,且指数为负数
	        if((equal(base,0.0)) && (exponent < 0)){
	            throw new Exception("0的负数次幂无意义");
	        }
	        //指数为0
	        if(exponent == 0)
	            return 1;
	        //指数为负数
	        if(exponent < 0)
	            result = powerWithExponent(1.0/base, -exponent);
	       //指数为正数
	        if(exponent>0)
	            result = powerWithExponent(base,exponent);
	        return result;
	    }
			//用累乘计算次方,这种方法效率不高
	        public double powerWithExponent(double base, int exponent){
	            double result = 1.0;
	            for(int i = 1; i <= exponent; i++)
	                result = result * base;
	            return result;
	        }
	        //用a^n=a^(n/2)*a^(n/2)或者a^((n-1)/2)*a^((n-1)/2)*a递归原理,减少乘法的次数
	        //用移位运算代替*/%运算,提高效率:右移一位相当于除以2,左移一位相当于乘以2,x与1按位与如果结果为1则x为奇数
	        public double powerWithExponent1(double base,int exponent){
	        	if(exponent == 0)
	        		return 1;
	        	if(exponent == 1)
	        		return base;
	        	double result = powerWithExponent(base, exponent >> 1);
	        	result *= result;
	        	//判断exponent是否为奇数,如果为奇数还需要再乘一遍base
	        	if((exponent & 0x1)==1)
	        		result = result*base;
	        	return result;
	        }
	       
	      //计算机表示小数(float和double)都有误差,不能直接用==判断两个小数是否相等。
	        //如果两个小数的绝对值很小,比如小于0.0000001,就可以认为它们相等。
	        public boolean equal(double num1,double num2){
	            if(((num1-num2)>-0.000000001)&&((num1-num2)<0.000000001))
	                return true;
	            else
	                return false;
	        }

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		

			Power p = new Power();
			System.out.println(p.power(2, -3));
	}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值