zoukankan      html  css  js  c++  java
  • 第16题:数值的整数次方

    题目描述

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

    代码的完整性:

    1.功能测试

    2.边界测试

    3.负面测试

    3种处理方法/优点/缺点

    1.返回值/与系统API一致/无法直接作为函数参数

    2.全局变量/可以直接作参数/可能忘记检查,有安全隐患

    3.抛出异常/逻辑明了/有些语言不支持异常

    思路

    //1.全局变量标记异常值
    bool g_InvalidInput = false;

    //大函数 

        //2.初始化全局变量 

        //3.如果输入底数为0,指数为负,返回0,且异常 

        //4.设置无符号变量存放指数的绝对值 

        //5.调用求指数的函数,设置double型储存指数的结果 

        //6.如果指数是负数,就求倒数

        //7.返回结果 


    //求指数的函数double,参数:底数double,指数unsigned int,返回值:结果double。这里的指数已经取了绝对值,所以是unsigned int。 

        //1.如果指数为0,返回1  
        //2.如果指数为1,返回底数 

        //由于数学知识可知,
        //如果exponent为偶数,result=base^(exponent/2)*base^(exponent/2)
        //如果exponent为偶数,result=base^((exponent-1)/2)*base^((exponent-1)/2)*base
        //3.使用递归,可以得到base^(exponent/2),即div2的结果,用右移一位,>>1会更快 

        //4.将上面递归函数得到的div2的结果相乘 

        //5.判断原来的指数的奇偶性,如果是奇数,就再乘以一个底数。这里用与位运算更快。 

        //6.返回结果

    我的:运行时间: 4 ms 占用内存:376K

    double PowerWithUnsignedExponent(double base, unsigned int exponent);
    
    //1.全局变量标记异常值
    bool g_InvalidInput = false;
    
    double Power(double base, int exponent) {
    	//2.初始化全局变量
    	g_InvalidInput = false;
    
    	//3.如果输入底数为0,指数为负,返回0,且异常
    	if (base == 0.0 && exponent<0)
    	{
    		g_InvalidInput = true;
    		return 0;
    	}
    
    	//4.设置无符号变量存放指数的绝对值
    	unsigned int absExponent = (unsigned int)exponent;
    	if (exponent<0)
    	{
    		absExponent = -exponent;
    	}
    
    	//5.调用求指数的函数,设置double型储存指数的结果
    	double result = PowerWithUnsignedExponent(base, absExponent);
    
    	//6.如果指数是负数,就求导
    	if (exponent<0)
    		result = 1 / result;
    
    	//7.返回结果
    	return result;
    
    }
    
    
    //求指数的函数double,参数:底数double,指数unsigned int,返回值:结果double。这里的指数已经取了绝对值,所以是unsigned int。
    double PowerWithUnsignedExponent(double base,unsigned int exponent)
    {
    
    	//1.如果指数为0,返回1
    	if (exponent == 0)
    		return 1;
    	//2.如果指数为1,返回底数
    	if (exponent == 1)
    		return base;
    
    	//由于数学知识可知,
    	//如果exponent为偶数,result=base^(exponent/2)*base^(exponent/2)
    	//如果exponent为偶数,result=base^((exponent-1)/2)*base^((exponent-1)/2)*base
    	//3.使用递归,可以得到base^(exponent/2),即div2的结果,用右移一位,>>1会更快
    	double result = PowerWithUnsignedExponent(base, exponent >> 1);
    
    	//4.将上面递归函数得到的div2的结果相乘
    	result = result*result;
    
    	//5.判断原来的指数的奇偶性,如果是奇数,就再乘以一个底数。这里用与位运算更快。
    	if (exponent & 1)
    		result *= base;
    
    	//6.返回结果
    	return result;
    }
    

     

    优化 运行时间: 4 ms 占用内存:468K

    class Solution {
    public:
        double Power(double base, int exponent) {
            if(exponent>0)
            {
                if(exponent==1)
                    return base;
                if(!exponent&1)//为偶数
                    return Power(base,exponent/2)*Power(base,exponent/2);
                else
                    return Power(base,exponent/2)*Power(base,exponent/2+1);
            }
            else if (exponent==0)
            {
                return 1;
            }
            else
            {
                return 1/Power(base,0-exponent);
            }
        }
    };

    不用递归 简单快速幂  运行时间: 3 ms 占用内存:484K 

    涉及到二分法的思想。 p的二进制位,如果某位等于1,就乘以base^该位置

    class Solution {
    public:
        double Power(double base, int exponent) {
            long long p = abs((long long)exponent);
          double r = 1.0;
            while(p){//用循环,不用递归。
                if(p & 1) r *= base;//奇数。上一层的结果乘以底数。
                base *= base;//上一层的结果相乘。
                p >>= 1;//进入下一层。
            }
            return exponent < 0 ? 1/ r : r;
        }
    };

    base = 0.0 ,exponent < 0 时 ,1/r = 1/0 报错...这个异常不应该在这个层次上处理,而是在调用的层次上...

    其它解法

     
    /**
     * 1.全面考察指数的正负、底数是否为零等情况。
     * 2.写出指数的二进制表达,例如13表达为二进制1101。
     * 3.举例:10^1101 = 10^0001*10^0100*10^1000。
     * 4.通过&1和>>1来逐位读取1101,为1时将该位代表的乘数累乘到最终结果。
     */
    public double Power(double base, int n) {
        double res = 1,curr = base;
        int exponent;
        if(n>0){
            exponent = n;
        }else if(n<0){
            if(base==0)
                throw new RuntimeException("分母不能为0"); 
            exponent = -n;
        }else{// n==0
            return 1;// 0的0次方
        }
        while(exponent){
            if(exponent&1)//奇数
                res*=curr;
            curr*=curr;// 翻倍
            exponent>>=1;// 右移一位
        }
        return n>=0?res:(1/res);       
    }
  • 相关阅读:
    10 个让人惊讶的 jQuery 插件
    URL编码方法比较
    Java大文件分片上传/多线程上传源码
    Java大文件分片上传/多线程上传代码
    Java大文件分片上传/多线程上传插件
    Java大文件分片上传/多线程上传控件
    python函数
    关于言谈
    Sql语句之select 5种查询
    openstack之网络基础
  • 原文地址:https://www.cnblogs.com/lightmare/p/10428841.html
Copyright © 2011-2022 走看看