【剑指Offer面试题】 九度OJ1514:数值的整数次方

代码质量——代码的完整性
确保代码的完整性:

  • 功能测试
  • 边界测试
  • 负面测试
    可能的错误输入
    错误处理的方法:
  • 返回值
  • 全局变量
  • 异常
  • -

题目链接地址:
http://ac.jobdu.com/problem.php?pid=1514

题目1514:数值的整数次方

时间限制:1 秒内存限制:128 兆特殊判题:否提交:2051解决:549
题目描述:
给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
输入:
输入可能包含多个测试样例。
对于每个输入文件,第一行输入一个整数T,表示测试案例的数目,接下来的T行每行输入一个浮点数base和一个整数exponent,两个数中间用一个空格隔开。
输出:
对应每个测试案例,
输出一个浮点数代表答案,保留两位小数即可。
样例输入:
5
1.0 10
0.0 -5
1.0 0
1.2 5
2.0 -1
样例输出:
1.00e+00f
INF
1.00e+00f
2.49e+00f
5.00e-01f
提示:
请特别注意不同的编译器对于科学计数法格式输出中指数位数的差别。建议使用九度Online Judge所使用的编译环境。

思路分析:

考察代码的完整性。
主要测试用例,考虑各种边界值,上指数为0,负数的情况。底数为0,负数的情况等等。
功能算法很简单:
- 用for循环逐个相乘在O(n)的时间结束;
- 用快速幂的思想,二分用O(log(n))的时间结束。
快速幂也即书上最优算法,代码:

/********************************* ----------------------------------- 【剑指Offer面试题】 九度OJ1514:数值的整数次方 ----------------------------------- Author:牧之丶 Date:2015年 Email:[email protected] **********************************/  
#include<stdio.h>
#include<stdlib.h> 
#include<string>
#include <math.h>
#include<stack>
#include <iostream>
using namespace std;

//用全局变量控制程序输入出错
bool InvalidInput = false;  
//求base的绝对值Exp次幂 
double PowerWithabsExp(double base,int Exp)
{
    if(Exp==0)
        return 1.0;
    if(Exp==1)
        return base;

    double result=PowerWithabsExp(base,Exp>>1);//Exp除以2
    result *=result;
    if(Exp &1==1)//判断Exp奇偶
        result *=base;
    return result;
}

//判断double类型相等
bool equal(double numberOne , double numberTwo)
{
    if (numberOne-numberTwo>-0.0000001&&numberOne-numberTwo<0.0000001)
    {
        return true;
    } 
    else
    {
        return false;
    }
}
//求base的Exp次幂 
double Power(double base,int Exp)  
{  
    InvalidInput=false;
    if (equal(base , 0.0) && Exp<0)
    {
        //非法输入
        InvalidInput=true;
        return 0.0;
    }
    int absExp=Exp;
    if (Exp<0)
    {
        absExp=-Exp;
    }
    double result=PowerWithabsExp(base,absExp);
    if (Exp<0)
    {
        result=1.0/result;
    }
    return result;   
}  

int main()  
{  
    int n,exp;  
    double base;  
    while(scanf("%d",&n) != EOF)  
    {  
        int i;  
        for(i=0;i<n;i++)  
        {  
            scanf("%lf %d",&base,&exp);  
            double result = Power(base,exp);  
            if(InvalidInput)  
                printf("INF\n");                
            else  
                printf("%.2ef\n",result);  
        }  
    }  
    return 0;  
}  
/************************************************************** Problem: 1514 Language: C++ Result: Accepted Time:80 ms Memory:1520 kb ****************************************************************/

另一种写法:以边界值驱动程序编写

自己写的思路,还是没有书上美观。
各种边界值:
  base为:
    正数:正常
    负数:(-base)^Exp= (-1)^Exp * base^Exp
    0:0的负数次方无意义,程序出错。0的正数次方为0
  Exp为:
    正数:正常
    负数:base^(-Exp) = 1 / base^Exp
    0:非零数的零次方都是1。0的0次方却有争议。请看0^0争议
    (在剑指书中,0^0等于1,不过九度里没有这个测试用例,所以为1为0独行)
  所有组合情况考虑全,就能以边界值驱动程序编写。
  

代码:

/********************************* ----------------------------------- 【剑指Offer面试题】 九度OJ1514:数值的整数次方 ----------------------------------- Author:牧之丶 Date:2015年 Email:[email protected] **********************************/ 
#include<stdio.h>
#include<stdlib.h> 
#include<string>
#include <math.h>
#include<stack>
#include <iostream>
using namespace std;
//判断double类型相等
bool equal(double numberOne , double numberTwo)
{
    if (numberOne-numberTwo>-0.0000001&&numberOne-numberTwo<0.0000001)
    {
        return true;
    } 
    else
    {
        return false;
    }
}
//用全局变量控制程序输入出错
bool InvalidInput = false; 
double Power(double base, int Exp)
{
    if(Exp == 0){
        return 1;           //这里0^0为1
    }else if(Exp < 0){
        if (equal(base,0.0)){
            //非法输入
            InvalidInput=true;
            return 0.0;
        }else{
            return Power(1.0 / base, -Exp);
        }
    }else{
        if(base < 0){
            return (Exp & 1 ? -1 : 1) * Power(-base, Exp);
        }else if (equal(base,0.0)){     //0的正数次方为0
            return 0.0;
        }
        double res = Power(base, Exp / 2);//此时base>=0,Exp>0
        if(Exp & 1){
            return res * res * base;
        }else{
            return res * res;
        }
    }
}


int main()  
{  
    int n,Exp,i;
    double base, result;

    while(scanf("%d", &n)!=EOF){
        for(i = 0; i < n; ++i){
            scanf("%lf%d", &base, &Exp);
            InvalidInput = false;  //每次都要先将InvalidInput置为false 
            result = Power(base, Exp);
            if(InvalidInput)  
                printf("INF\n");                
            else 
                printf("%.2ef\n",result);  
        }
    }
    return 0;  
}  
/************************************************************** Problem: 1514 Language: C++ Result: Accepted Time:80 ms Memory:1520 kb ****************************************************************/

总结:

1. 设置全局变量标识是否出错。
2. 判断double类型相等,不能直接用==
3. 用快速幂的思想,二分用O(log(n))的时间结束
4. 右移运算符代替除以2
5. 位与1运算代替求余运算(%)判断奇偶
6. 细节决定成败!!!

你可能感兴趣的:(面试题,剑指offer,代码的完整性)