16 数值的整数次方 (第3章 高质量的代码)

题目描述:

给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。不得使用库函数,同时不需要考虑大数问题。

不只要通过测试,要更着重代码的优化

测试用例:

base与exponent分别取正数、0、负数  共3*3九种情况

解题思路:

1)为base与exponent区分正数、0、负数  全面但是不够高效率的解法

class Solution {
public:    bool g_InvalidInput = false;
    double Power(double base, int exponent) {
        if(base==0 && exponent<=0){  //相等这是否有问题??? 修改为 abs(base-0.0)<10e-10
            //0^0没有意义 而1/0 0不能为分母            g_InvalidInput = true; //用于标记是由于出错,返回0(此时该值为true),若是由计算结果返回0,该值为false。
            return 0.0;
        }

        double result = 1.0;
        //确定是正值,用无符号比较好
        unsigned int absExponent = (unsigned int)(exponent); //int到unsigned int要显示转换
        if(exponent<0)
            absExponent = (unsigned int)(-exponent);
        /*if(exponent<0)
            int absExponent = -exponent;  //for处会显示没有定义absExponent变量
        else
            int absExponent = exponent;*/

        for (int i=0;i<absExponent;i++) //有更高效的求解方法
            result*=base;

        if(exponent<0)
            result=1.0/result; //用1.0比较好,而非1。 1也可以

        return result;
    }
};

注:[1]  对于double类型而言,由于精度的原因,不能用等号判断两个小数是否相等。因为double类型的表示往往是不精确的(近似表示),有精度范围的那种。如果是运算结果,即使都是0.0,也不保证相等!一般用一个容差e(很小的值)。

[2] 上述代码采用全局变量 g_InvalidInput 来标识是否出错(函数返回0时,是由于计算结果为零,还是错误的输入)。但是在使用函数返回值时,如 double result = Power(2,3); 调用时,常常容易忘记检查 g_InvalidInput 以判断是否出错

2)全面又高效的算法 时间复杂度O(logn)

当exponent=32时,要计算31次乘法。但是如果知道16的平方,再平方即可得到最终解。这样经过5次计算就可以得到最终解。

//实现1:递归调用class Solution {
public:
    bool g_InvalidInput = false;
    double Power(double base, int exponent) {
        if(abs(base-0.0)<10e-10 && exponent<=0){
            //0^0没有意义 而1/0 0不能为分母
            g_InvalidInput = true; //用于标记是由于出错,返回0(此时该值为true),若是由计算结果返回0,该值为false。

            return 0.0;
        }

        double result = 1.0;
        //确定是正值,用无符号比较好
        unsigned int absExponent = (unsigned int)(exponent); //int到unsigned int要显示转换
        if(exponent<0)
            absExponent = (unsigned int)(-exponent);
        /*if(exponent<0)
            int absExponent = -exponent;  //for处会显示没有定义absExponent变量
        else
            int absExponent = exponent;*/

        for (int i=0;i<absExponent;i++)
            result*=base;

        if(exponent<0)
            result=1.0/result; //用1.0比较好,而非1。 1也可以

        return result;
    }
    //改进的代码
    double PowerWithUnsignedExponent(double base, unsigned int exponent){
        if(exponent==0)  //奇数终止 1/2=0
            return 1;
        if(exponent==1)  //偶数终止 2/2=1
            return base;                //递归调用
        double result = PowerWithUnsignedExponent( base, exponent>>1); //右移代替除以2
        result*=result;
        if(exponent&0x1==1)  //位与操作,最后一位是1,则一定是奇数。最后一位是0,则一定是偶数。  exponent%2==1 也可以判断,但是效率很低
            result*=base;
        return result;
    }
};  

代码中的两处细节:判断base是否为0,以及用位运算代替乘除法以及取余运算。

位运算的效率比乘除法及求余运算的效率要高很多!!  

//实现2:循环实现
class Solution {
public:
    bool g_InvalidInput = false;
    double Power(double base, int exponent) {
        double result = 1,currBase = base;
        int absExponent;
        if(exponent>0){
            absExponent = exponent;
        }else if(exponent<0){
            if(base==0.0){
                g_InvalidInput = true;
                return 0.0;
                //throw new RuntimeException("分母不能为0");
            }
            absExponent = -exponent;
        }else{// n==0
            return 1;// 任何数的0次幂(包括0的0次方)。
        }
        //循环实现
        while(absExponent!=0){
            if((absExponent&1)==1) //奇数
                result*=currBase;
            currBase*=currBase;// 翻倍,记录的是基数
            absExponent>>=1;// 右移一位,除以2
        }

        return exponent>=0?result:(1/result);

    }
};  

指数计算:

  • 当n为偶数,a^n =(a^n/2)*(a^n/2)
  • 当n为奇数,a^n = a^[(n-1)/2] * a^[(n-1)/2] * a
  • 2^11 = 2^1 * 2^2 * 2^8     //其中11的二进制表示位 :1011 将其拆分为:100000100001
  • 2^1011 = 2^0001 * 2^0010  * 2^1000

原文地址:https://www.cnblogs.com/GuoXinxin/p/10419228.html

时间: 2024-10-03 02:45:48

16 数值的整数次方 (第3章 高质量的代码)的相关文章

16. 数值的整数次方

面试题16. 数值的整数次方 实现函数double Power(double base, int exponent),求base的exponent次方.不得使用库函数,同时不需要考虑大数问题. 示例 1: 输入: 2.00000, 10 输出: 1024.00000 示例 2: 输入: 2.10000, 3 输出: 9.26100 示例 3: 输入: 2.00000, -2 输出: 0.25000 解释: 2-2 = 1/22 = 1/4 = 0.25 说明: -100.0 < x < 100

菜鸟系列 Golang 实战 Leetcode —— 面试题16. 数值的整数次方

实现函数double Power(double base, int exponent),求base的exponent次方.不得使用库函数,同时不需要考虑大数问题. ? 示例 1: 输入: 2.00000, 10 输出: 1024.00000 示例?2: 输入: 2.10000, 3 输出: 9.26100 示例?3: 输入: 2.00000, -2 输出: 0.25000 解释: 2-2 = 1/22 = 1/4 = 0.25 ? 说明: -100.0 <?x?< 100.0 n?是 32 位

剑指offer-第三章高质量的代码(输出该链表中倒数第K个节点)

题目:输入一个链表,输出这个链表中倒数第K个节点.(代码的鲁棒性) 思路:用两个指针p1和p2,都指向头节点,开始的时候,p2不动,p1移动k-1次,指向第k个节点.此时,如果p1->next!=null,则同时移动P1和p2.直到p1指向最后一个节点.此时,P2指向倒数第k个节点. C++代码: #include<iostream> using namespace std; struct ListNode { int m_nValue; ListNode* m_pNext; }; Li

剑指offer—第三章高质量的代码(按顺序打印从1到n位十进制数)

题目:输入一个数字n,按照顺序打印出1到最大n位十进制数,比如输入3,则打印出1,2,3直到最大的3位数999为止. 本题陷阱:没有考虑到大数的问题. 本题解题思路:将要打印的数字,看成字符串,不足位的,高位补0.打印字符串的时候要对数字进行判断,不要将高位的0打印出来.打印字符串的结束条件是,当最高位产生进位时结束. c++代码: #include<iostream> using namespace std; //字符串模拟加法 bool Increment(char* number) {

22 链表中倒数第k个节点(第3章 高质量的代码-代码的鲁棒性)

题目描述: 输入一个链表,输出该链表中倒数第k个结点. 尾节点是倒数第一个节点 测试用例:   功能测试(第k个节点在中间.是头节点.是尾节点) 特殊输入测试(链表头节点是nullptr指针.链表的头节点个数小于k.k=0) 解题思路: 1)使用两个指针,一个指针先移动k步,如果链表小于k,终止返回nullptr.然后两个指针同时移动,知道后一个指针移出最后一个节点 //实现1/* struct ListNode { int val; struct ListNode *next; ListNod

25 合并两个排序的链表(第3章 高质量的代码-代码的鲁棒性)

题目描述: 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则. 测试用例:   1)功能测试(输入的两个链表有多个节点:节点的值互不相同或者存在值相等的多个节点) 2)特殊输入测试(连个链表的一个或者两个头节点为nullptr指针:两个链表中只有一个节点)为什么单独列出来,哪里特殊?? 解题思路: 1)将两个链表的值按大小存入到队列queue中,然后按照队列的值重新生成一个新的链表. class Solution { public: ListNode*

面试题16:数值的整数次方

// 面试题16:数值的整数次方 // 题目:实现函数double Power(double base, int exponent),求base的exponent // 次方.不得使用库函数,同时不需要考虑大数问题. 解题思路: 解题并不难,重要的是要考虑到输入的各种情况,并且有相应的处理. double和int都是可以取负数和0的,如果base取0,exponent<0,结果显然是不存在的. base取0,exponent取非负,直接返回1就可以了. 其他情况,正常运算就好,要注意如果expo

剑指Offer--第16题 数值的整数次方

第16题 数值的整数次方 题目:给定一个double类型的浮点数base和int类型的整数exponent.求base的exponent次方. 思路 看到有点懵,第一感觉觉得是不是应该考虑0的0次或者负数情况,还有就是浮点类型没办法使用"="号,最后自己以偷懒的方式直接调用Java的API,如果面试题中不让调用库函数,那么基本上这题就是挂了可能. 以上题目描述来自牛客,没有对使用做限制.真正的剑指offer上有限制条件不得使用库函数,同时不需要考虑大数问题. 自己的low代码 publ

【剑指offer】数值的整数次方

转载请注明出处:http://blog.csdn.net/ns_code/article/details/25506085 剑指offer上的第十一题,九度OJ上测试通过. 题目描述: 给定一个double类型的浮点数base和int类型的整数exponent.求base的exponent次方. 输入: 输入可能包含多个测试样例.对于每个输入文件,第一行输入一个整数T,表示测试案例的数目,接下来的T行每行输入一个浮点数base和一个整数exponent,两个数中间用一个空格隔开. 输出: 对应每